// languagecomponents.cpp: implementation of the signal class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "math.h"
#include "waveeditor.h"
#include "languagecomponents.h"
#include "WaveeditorDialogs.h"
#include "graphdata.h"
#include "waveeditorDoc.h"
#include "myformatstring.h"
#include "MainFrm.h"
#include "mymessages.h"	// Added by ClassView
#include <algorithm>

#include <new>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

enum	group_Type	{W_SIMPLE=3,W_COMPLEX	,W_FRAME,W_DEFAULT	}	groupType;
enum	signal_Type	{W_CONST ,W_CLK		,W_PWM	,W_PWM_FILE, W_GROUP	}	signalType;
unsigned long													writeline;
WritingSatusDialog												*wsdialog;
BOOL															wsdialogexist;
CString															old_vector;
int		myfputs		( const char *string, FILE *stream )
{
	fputs(string,stream);
	writeline++;
	if((wsdialogexist	==	TRUE)&&((writeline % 200) == 0))
	{
		wsdialog->SetLineNumber(writeline);
	}
	return 1;
}

__int64 IntervalCompare( __int64 ComparingValue, __int64 Minimum, __int64 Maximum )
{
	if ( ComparingValue < Minimum )
	{
		return Minimum;
	}
	else if (ComparingValue > Maximum )
	{
		return Maximum;
	}
	else
	{
		return ComparingValue;
	}
}

__int64 CStringToLong ( CString String )
{
	return _atoi64(String);
}
CString Long64ToCString ( __int64 value )
{
	char Line[30];
	_i64toa(value,Line,10);
	return (CString)Line;
}

CString GetFileExtension( CString Path )
{
	int ExtensionPosition = Path.ReverseFind( '.' ) + 1;
	CString Extension;
	Extension = Path.Mid( ExtensionPosition );
	Extension.MakeLower();
	return Extension;
}

///////////////////////////////////
//////// _LineMembersStruct
///////////////////////////////////

bool _LineMembers::IsTimeMarkClosing()
{
	CArray<CString, CString> aszEndMarks;
	aszEndMarks.Add( "END" );
	aszEndMarks.Add( "STOP" );
	aszEndMarks.Add( "DONE" );
	aszEndMarks.Add( "FINISH" );
	CString AnalyzingComment = Comment;
	AnalyzingComment.MakeUpper();
	bool Result = false;
	for ( int i = 0; i < aszEndMarks.GetSize(); i++)
	{
		if ( AnalyzingComment.Find( aszEndMarks[i]) != -1 )
		{
			Result = true;
			break;
		}
	}
	return Result;
}

///////////////////////////////////////
/////// Signal Struct
///////////////////////////////////////

Signal::Signal():Name(""),FirstStatus(0),TimeType(0),SignalType(0)
{
}

Signal::Signal( const Signal &OldSignal )
{
	Copy( OldSignal );
}

Signal::Signal( LineMembers &LineMembrs )
{
	Name = LineMembrs.Name;
	TimeType = LineMembrs.TimeType;
	SignalType = LineMembrs.Type;
	if ( LineMembrs.Type == SIGNAL_WITH_SQUARE_BRACKETS )
	{
		if ( LineMembrs.IsTimeMarkClosing() )
		{
			FirstStatus = 1;
		}
		else
		{
			FirstStatus = 0;
		}
	}
	else
	{
		FirstStatus = 0;
		Changes.Add( LineMembrs.TimeMark - 1 );
		Comments.Add( LineMembrs.Comment );
	}
	Comments.Add( LineMembrs.Comment );
	Changes.Add( LineMembrs.TimeMark );
}

void Signal::operator=(Signal &OldSignal)
{
	Copy( OldSignal );
}

void Signal::Copy( const Signal &OldSignal )
{
	Name = OldSignal.Name;
	
	FirstStatus = OldSignal.FirstStatus;
	Changes.Copy( OldSignal.Changes );
	Comments.Copy( OldSignal.Comments );
	TimeType = OldSignal.TimeType;
	SignalType = OldSignal.SignalType;
}

Signal::~Signal()
{
	Changes.RemoveAll();
	Comments.RemoveAll();
}



//////////////////////////////////////////////////////////////////////
// WaveSignalStatisticsStruct
//////////////////////////////////////////////////////////////////////

WaveSignalStatistics::WaveSignalStatistics()
{
	for( int i = 0; i < 2; i++ )
	{
		MaxTimeInLevel[i] = 0;
		MinTimeInLevel[i] = -1;
		SumOfTimesInLevel[i] = 0;
		NumberOfLevels[i] = 0;
	}
}

void WaveSignalStatistics::UpdateWaveSignalStatistics( WaveSignalStatistics Statistics )
{
	for( int i = 0; i < 2; i++ )
	{
		if ( MaxTimeInLevel[i] < Statistics.MaxTimeInLevel[i] )
		{
			MaxTimeInLevel[i] = Statistics.MaxTimeInLevel[i];
		}
		if ( MinTimeInLevel[i] > Statistics.MinTimeInLevel[i] )
		{
			MinTimeInLevel[i] = Statistics.MinTimeInLevel[i];
		}
		SumOfTimesInLevel[i] += Statistics.SumOfTimesInLevel[i];
		NumberOfLevels[i] += Statistics.NumberOfLevels[i];
	}
	return;
}

void WaveSignalStatistics::ConvertToMS( int TimeDivider )
{
	for( int i = 0; i < 2; i++ )
	{
		MaxTimeInLevel[i] /= TimeDivider;
		MinTimeInLevel[i] /= TimeDivider;
		SumOfTimesInLevel[i] /= TimeDivider;
	}
	return;
}

//////////////////////////////////////////////////////////////////////
// ScenarioSignals Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

ScenarioSignals::ScenarioSignals(mymessages	*_StatusList) : 
    Name(NULL),
    OriginalName(NULL),
    SignalUsed(NULL),
    SignalOrder(NULL),
    SignalPos(NULL),
	SignalYSize(NULL),
	SignalsInGroup(NULL),
    SignalMarked(NULL),
	Type(NULL),
	Rules(NULL),
	SignalBackgroundColor(NULL)
{
	Exist		=	FALSE;
	StatusList	=	_StatusList;
	GraphDeltaY	=	20;
	GraphOffsetY	=	4;
	NumberOfSignals = 0;
	LastMarkedSignalNumber = -1;
}

ScenarioSignals::~ScenarioSignals()
{
    FreeSignalDataArrays();
}

void ScenarioSignals::FreeSignalDataArrays()
{
    delete[]  Name;
    delete[]  OriginalName;
    delete[]  SignalUsed;
    delete[]  SignalOrder;
    delete[]  SignalPos;
	delete[]  SignalYSize;
    delete[]  SignalMarked;
	delete[]  Type;
	delete[]  SignalBackgroundColor;
	delete[]  Rules;
	
	for ( ULONG i = 0; i < NumberOfSignals; i++ )
	{
		if( SignalsInGroup != NULL )
		{		
			delete SignalsInGroup[i];
		}
	}
	delete[]  SignalsInGroup;

    Name = NULL;
    OriginalName = NULL;
    SignalUsed = NULL;
    SignalOrder = NULL;
    SignalPos = NULL;
	SignalYSize = NULL;
	SignalsInGroup = NULL;
    SignalMarked = NULL;
	Type = NULL;
	SignalBackgroundColor = NULL;
	Rules = NULL;

	LastMarkedSignalNumber = -1;
}

BOOL ScenarioSignals::SignalsExist()
{
	return Exist;
}

/*CString ScenarioSignals::GetFileName()
{
	return filename;
}*/

bool ScenarioSignals::IncludeMarkedSignalsIntoGroup( int NumberOfSignal )
{
	int NumberOfSignals = GetNumberOfSignals();
	for( int i = 0; i < NumberOfSignals; i++ )
	{
		if ( CheckIfSignalMarked( i ) )
		{
			AddSignalToArray( SignalsInGroup[NumberOfSignal], i );
		}
	}
	if ( SignalsInGroup[NumberOfSignal]->GetCount() == 0 || TryForSimilarGroup( NumberOfSignal ) == true )
	{
		return false;
	}
	return true;
}

bool ScenarioSignals::TryForSimilarGroup( int NumberOfSignal )
{
	int NumberOfSignals = GetNumberOfSignals();
	bool IsSimilar;
	for( int i = 0; i < NumberOfSignals; i++ )
	{
		IsSimilar = true;
		if ( SignalsInGroup[NumberOfSignal]->GetCount() == SignalsInGroup[i]->GetCount() && (i != NumberOfSignal) )//!( i == NumberOfSignal && SignalUsed[ NumberOfSignal ] == true ) )
		{
			for( int j = 0; j < SignalsInGroup[NumberOfSignal]->GetCount(); j++ )
			{
				if ( FindInArray( (*SignalsInGroup[NumberOfSignal])[j], SignalsInGroup[i] ) == false )
				{
					IsSimilar = false;
					break;
				}
				
			}
			if ( IsSimilar == true )
			{
				StatusList->AddMessage( "Such signal already exists - " + GetSignalName( i ) );
				this->AddShowSignal( GetSignalName( i ) );
				return true;
			}
		}
	}
	return false;
}

bool ScenarioSignals::FindInArray( int Element, CArray<int,int> *SignalsInGroup )
{
	for ( int i = 0; i < SignalsInGroup->GetCount(); i++ )
	{
		if ( SignalsInGroup->GetAt( i ) == Element )
		{
			return true;
		}
	}
	return false;
}

void ScenarioSignals::AddSignalToArray( CArray<int, int> *ChosenSignals, int NumberOfSignal )
{
	int NumOfIncludedSignals = SignalsInGroup[NumberOfSignal]->GetCount();
	for ( int i = 0; i < NumOfIncludedSignals; i++ )
	{
		AddSignalIfAbsent( ChosenSignals, (*SignalsInGroup[NumberOfSignal])[i]);
	}
}

void ScenarioSignals::AddSignalIfAbsent( CArray<int, int> *ChosenSignals, int NumberOfSignal )
{
	for( int i = 0; i < ChosenSignals->GetCount(); i++)
	{
		if ( (*ChosenSignals)[i] == NumberOfSignal )
		{
			return;
		}
	}
	ChosenSignals->Add( NumberOfSignal );
}

BOOL ScenarioSignals::LoadSignalsFromScriptFile(CString FileName )
{
	bool Result = false;

	CArray<CString,CString> SignalNames;
	
	FillListOfSignalNamesAndUpdateNumberOfSignals( &SignalNames, FileName );
	
	FreeSignalDataArrays();
    
	if ( NumberOfSignals > 0 )
    {
        if ( TryToCreateArraysOfSignalsData() == true )
		{
		    Exist = TRUE;
			FillNames( &SignalNames );
			Result = true;
		}
    }
	else
	{
		StatusList->AddMessage("No one signal was loaded");
	}
	return Result;
}

bool ScenarioSignals::LoadSignalsFromArray( const CArray< Signal, Signal > &Signals )
{
	bool Result = false;
	if ( Signals.GetCount() > 0 )
	{
		FreeSignalDataArrays();
		NumberOfSignals = Signals.GetCount();
		if ( TryToCreateArraysOfSignalsData() == true )
		{
			Exist = TRUE;
			FillFields( Signals );
			Result = true;
		}
	}
	else
	{
		StatusList->AddMessage("There is no one signal in array");
	}
	return Result;
}

bool ScenarioSignals::AddNewGroupFromMarked( CString &NameOfNewGroup )
{
	NameOfNewGroup = "Group";
	AddNewDefaultSignal( NameOfNewGroup );
	SignalsInGroup[ NumberOfSignals - 1 ]->RemoveAll();
	if ( IncludeMarkedSignalsIntoGroup( NumberOfSignals - 1 ) == false )
	{
		DeleteSignalFromScenarioSignals( NumberOfSignals - 1 );
		return false;
	}
	NameOfNewGroup = Name[ NumberOfSignals - 1 ] = CreateNameFromIncludedSignals( NumberOfSignals - 1 );
	Type			[ NumberOfSignals - 1 ]		=	GROUP_OF_SIGNALS;
	SignalYSize		[ NumberOfSignals - 1 ]		=	GetSizeFromNumberOfSignals( NumberOfSignals - 1 );
	return true;
}

CString ScenarioSignals::CreateNameFromIncludedSignals( int NumberOfSignal )
{
	CString Name = "Group: " + (GetSignalName( SignalsInGroup[NumberOfSignal]->GetAt( 0 ) )).Mid( 0, 4 );
	CString TempName;
	for ( int i = 1; i < SignalsInGroup[NumberOfSignal]->GetCount(); i++ )
	{
		TempName = GetSignalName( SignalsInGroup[NumberOfSignal]->GetAt( i ) );
		TempName = TempName.Mid( 0, 4 );
		Name += "_" + TempName;
	}
	return Name; 
}

void ScenarioSignals::AddNewDefaultSignal( CString &NameOfSignal )
{
	ScenarioSignals NewScenarioSignals( StatusList );
	NewScenarioSignals.NumberOfSignals = GetNumberOfSignals();
	NewScenarioSignals.TryToCreateArraysOfSignalsData();
	NewScenarioSignals.CopyArrays( this );
	FreeSignalDataArrays();
	NumberOfSignals++;
	TryToCreateArraysOfSignalsData();
	CopyArrays( &NewScenarioSignals );

	CString NameOfNewSignal = NameOfSignal;
	int i = 0;
	while( this->GetSignalNumber( NameOfNewSignal ) >= 0 )
	{
		NameOfNewSignal = NameOfSignal+"_"+Long64ToCString((__int64)i);
		i++;
	}
	SetDefaultsForSingleSignal ( NumberOfSignals - 1 );
	NameOfSignal = Name[NumberOfSignals - 1] = OriginalName[NumberOfSignals - 1] = NameOfNewSignal;
}

void ScenarioSignals::DeleteSignalFromScenarioSignals( int NumberOfSignal )
{
	if( IfShowSignal(NumberOfSignal) == TRUE)
	{
		PushSignalToEnd(NumberOfSignal);
	}

	ScenarioSignals NewScenarioSignals( StatusList );
	NewScenarioSignals.NumberOfSignals = GetNumberOfSignals();
	NewScenarioSignals.TryToCreateArraysOfSignalsData();
	NewScenarioSignals.CopyArrays( this );
	FreeSignalDataArrays();
	NumberOfSignals--;
	TryToCreateArraysOfSignalsData();
	for ( ULONG i = 0, k = 0; i < NewScenarioSignals.NumberOfSignals; i++ )
	{
		if( i!=NumberOfSignal )
		{
			Name[k] = NewScenarioSignals.Name[i];
			OriginalName[k] = NewScenarioSignals.OriginalName[i];
			SignalUsed[k] = NewScenarioSignals.SignalUsed[i];
			SignalOrder[k] = NewScenarioSignals.SignalOrder[i];
			SignalMarked[k] = NewScenarioSignals.SignalMarked[i];
			Type[k] = NewScenarioSignals.Type[i];
			SignalBackgroundColor[k] = NewScenarioSignals.SignalBackgroundColor[i];
			Rules[k] = NewScenarioSignals.Rules[i];
			for (int j = 0; j < NewScenarioSignals.SignalsInGroup[i]->GetCount(); j++ )
			{
					SignalsInGroup[k]->Add( (*NewScenarioSignals.SignalsInGroup[i])[j] );
					if ( (*SignalsInGroup[k])[SignalsInGroup[k]->GetUpperBound()] > NumberOfSignal )
					{
						(*SignalsInGroup[k])[SignalsInGroup[k]->GetUpperBound()]--;
						continue;
					}
					if ( (*SignalsInGroup[k])[SignalsInGroup[k]->GetUpperBound()] == NumberOfSignal )
					{
						SignalsInGroup[k]->RemoveAt( SignalsInGroup[k]->GetUpperBound() );
					}
			}
			SignalYSize[k] = this->GetSizeFromNumberOfSignals( k );
			k++;
		}
	}
	int TempNumber;
	for ( ULONG i = 0; i < NewScenarioSignals.NumberOfSignals; i++ )
	{
		TempNumber = GetSignalNumber( i );
		if ( TempNumber < 0 )
		{
			continue;
		}
		SignalPos[TempNumber].y = GetSignalPosByOrder( i );
	}
}

int ScenarioSignals::GetSizeFromNumberOfSignals( int NumberOfSignal)
{
	return GetDistanceBetweenTwoLinesInGroup() * ( SignalsInGroup[NumberOfSignal]->GetCount()-1) + GraphDeltaY;
}

void ScenarioSignals::CopyArrays( ScenarioSignals* OldValues )
{
	int Limit = min( NumberOfSignals, OldValues->NumberOfSignals );
	for ( int i = 0; i < Limit; i++ )
	{
		Name[i] = OldValues->Name[i];
		OriginalName[i] = OldValues->OriginalName[i];
		SignalUsed[i] = OldValues->SignalUsed[i];
		SignalOrder[i] = OldValues->SignalOrder[i];
		SignalPos[i] = OldValues->SignalPos[i];
		SignalYSize[i] = OldValues->SignalYSize[i];
		for (int j = 0; j < OldValues->SignalsInGroup[i]->GetCount(); j++ )
		{
			SignalsInGroup[i]->Add( (*OldValues->SignalsInGroup[i])[j] );
		}
		SignalMarked[i] = OldValues->SignalMarked[i];
		Type[i] = OldValues->Type[i];
		SignalBackgroundColor[i] = OldValues->SignalBackgroundColor[i];
		Rules[i] = OldValues->Rules[i];
	}
}

void ScenarioSignals::FillListOfSignalNamesAndUpdateNumberOfSignals( CArray<CString,CString> *SignalNames, CString FileName)
{
	CStdioFile ScriptFile;
	if ( !ScriptFile.Open( FileName, CFile::modeRead ) )
	{
		StatusList->AddMessage("File could not be opened");
		return;
	}

	CString	OriginalCommand, Command;
	NumberOfSignals	=	0;

	long PositionOfSignalNameBegin, PositionOfSignalNameEnd;
	long NumberOfLine = 0;
	while( ScriptFile.ReadString( OriginalCommand ) )
	{
		NumberOfLine++;
		int CommentPos = OriginalCommand.Find( "//" );
		if ( CommentPos >= 0 )
		{
			OriginalCommand = OriginalCommand.Mid( 0, CommentPos );
		}
		OriginalCommand.Mid( 0, OriginalCommand.Find( "//" ) );
		Command = OriginalCommand;
		Command.MakeLower();
        if ( (PositionOfSignalNameBegin = Command.Find("signal", 0)) >= 0)
		{	
			PositionOfSignalNameBegin += 6;
			if ( (PositionOfSignalNameEnd = Command.ReverseFind('=')) < 0 )
			{
				StatusList->AddMessage("Error in string "+Long64ToCString(NumberOfLine));
			}
			else
			{
				OriginalCommand = OriginalCommand.Mid(PositionOfSignalNameBegin, PositionOfSignalNameEnd - PositionOfSignalNameBegin);
				OriginalCommand.Trim();
				if ( SignalIsFound ( SignalNames, OriginalCommand ) == false )
				{
					SignalNames->Add( OriginalCommand );
					NumberOfSignals++;
				}
			}
		}
    }
	ScriptFile.Close();
}

bool ScenarioSignals::SignalIsFound ( CArray<CString,CString> *SignalNames, CString OriginalName )
{
	for ( ULONG i = 0; i < NumberOfSignals; i++ )
	{
		if ( (*SignalNames)[i] == OriginalName )
		{
			return true;
		}
	}
	return false;
}

bool ScenarioSignals::TryToCreateArraysOfSignalsData()
{
	try
    {
        Name = new CString[NumberOfSignals];
        OriginalName = new CString[NumberOfSignals];
        SignalUsed = new BOOL[NumberOfSignals];
        SignalOrder = new int[NumberOfSignals];
        SignalPos = new CPoint[NumberOfSignals];
		SignalYSize = new int[NumberOfSignals];
		SignalsInGroup = new CArray<int, int>*[NumberOfSignals];
		for (UINT i = 0; i < NumberOfSignals; i++)
		{
			SignalsInGroup[i] = new CArray<int, int>();
		}
        SignalMarked = new BOOL[NumberOfSignals];
		Type = new int[NumberOfSignals];
		SignalBackgroundColor = new long[NumberOfSignals];
		Rules = new HighlightingRule[NumberOfSignals];
		
		memset( SignalUsed, 0, NumberOfSignals * sizeof(BOOL));
		memset( SignalOrder, 255, NumberOfSignals * sizeof(int));
		memset( SignalYSize, 0, NumberOfSignals * sizeof(int));
		memset( SignalMarked, 0, NumberOfSignals * sizeof(BOOL));
		memset( Type, 0, NumberOfSignals * sizeof(int));
		memset( SignalBackgroundColor, 0, NumberOfSignals * sizeof(long));
    }
    catch (std::bad_alloc)
    {
        FreeSignalDataArrays();
        StatusList->AddMessage("ERROR:Insufficient memory to open signalfile");
		return false; 
    }
	return true;
}

void ScenarioSignals::FillNames( CArray<CString,CString> *SignalNames )
{
	for ( ULONG i = 0; i < NumberOfSignals; i++ )
	{
		Name[i] = OriginalName[i] = (*SignalNames)[i];
		//Name[i] = (*SignalNames)[i].MakeLower();
	}
}

void ScenarioSignals::FillFields( const CArray<Signal, Signal> &Signals )
{
	for ( ULONG i = 0; i < NumberOfSignals; i++ )
	{
		Name[i] = OriginalName[i] = Signals[i].Name;
		SetDefaultsForSingleSignal( i );
		Type[i] = Signals[i].SignalType;
	}
}

CString ScenarioSignals::GetSignalName( int Index )
{
	return CheckSignalIndex( Index ) ? Name[Index] : "";
}

CString ScenarioSignals::GetOriginalName( int Index)
{
	return CheckSignalIndex( Index ) ? OriginalName[Index] : "";
}

HighlightingRule ScenarioSignals::GetRule ( int NumberOfSignal )
{
	return Rules[NumberOfSignal];
}

int ScenarioSignals::GetSignalNumberInGroupFromGraphView( int CoordY )
{
	int SignalNumber = GetSignalNumber( CPoint(0, CoordY) );
	if ( SignalNumber == -1 )
	{
		return -1;
	}
	int IndentInGroup = CoordY - GetSignalPos( SignalNumber ) - GraphOffsetY;
	int DistanceBetweenTwoSignals = GetDistanceBetweenTwoLinesInGroup();
	if ( IndentInGroup > -2 &&(IndentInGroup + 1) % (DistanceBetweenTwoSignals / 2) < 3 )
	{
		int result = ( (IndentInGroup + 1) / DistanceBetweenTwoSignals ) - ( (IndentInGroup +1)%DistanceBetweenTwoSignals / (DistanceBetweenTwoSignals / 2) );
		if ( result < 0 || result > SignalsInGroup[SignalNumber]->GetUpperBound() )
		{
			return -1;
		}
		return result;
	}
	return -1;
}

int ScenarioSignals::CheckIfHighOrLowLevelOfSignal( int CoordY )
{
	int SignalNumberInGroup = GetSignalNumberInGroupFromGraphView( CoordY );
	if ( SignalNumberInGroup < 0 )
	{
		return -1;
	}
	int IndentBetweenTwoSignals = GetDistanceBetweenTwoLinesInGroup();
	return 1 - ( CoordY - GetSignalPos( GetSignalNumber( CPoint(0, CoordY) ) ) - GraphOffsetY + 1 ) % IndentBetweenTwoSignals / (IndentBetweenTwoSignals / 2);
}

int ScenarioSignals::GetSignalPositionNumberInGroupFromButtonView( int CoordY )
{
	int SignalNumber = GetSignalNumber( CPoint(0, CoordY) );
	if ( SignalNumber == -1 )
	{
		return -1;
	}
	int IndentInGroup = CoordY - GetSignalPos( SignalNumber );
	if ( IndentInGroup < 0 || IndentInGroup > SignalYSize[SignalNumber] )
	{
		return -1;
	}
	int DistanceBetweenTwoSignals = GetDistanceBetweenTwoLinesInGroup();
	return min( (IndentInGroup - GraphOffsetY) / DistanceBetweenTwoSignals, GetSignalsInGroup( SignalNumber )->GetUpperBound() );
}

int ScenarioSignals::GetSignalPositionNumberInGroupFromButtonView( int NumberOfSignal, int CursorYPosition )
{
	int NewPositionNumberInGroup;
	if ( CursorYPosition < GetSignalPos( NumberOfSignal ) )
	{
		NewPositionNumberInGroup = 0;
	}
	else if ( CursorYPosition >= GetSignalEndPos( NumberOfSignal ) )
	{
		NewPositionNumberInGroup = GetSignalsInGroup( NumberOfSignal )->GetUpperBound();
	}
	else
	{
		NewPositionNumberInGroup = GetSignalPositionNumberInGroupFromButtonView( CursorYPosition );
	}
	return NewPositionNumberInGroup;
}

CPoint ScenarioSignals::GetPositionsOfSignalInGroup( ULONG SignalNumber, int SignalInGroupNumber )
{
	if ( SignalNumber > NumberOfSignals || 
		 SignalNumber < 0 || 
		 SignalInGroupNumber < 0 || 
		 SignalInGroupNumber > GetSignalsInGroup( SignalNumber )->GetCount() )
	{
		return CPoint(-1,-1);
	}
	CPoint Result;
	int DistanceBetweenTwoSignals = GetDistanceBetweenTwoLinesInGroup();
	Result.x = GetSignalPos( SignalNumber ) + DistanceBetweenTwoSignals * SignalInGroupNumber + GraphOffsetY;
	Result.y = Result.x + (GraphDeltaY - 2*GraphOffsetY);
	Result.x -= (!SignalInGroupNumber) * GraphOffsetY;
	Result.y += (!( SignalInGroupNumber - GetSignalsInGroup( SignalNumber )->GetUpperBound() )) * GraphOffsetY;
	return Result;

}

int ScenarioSignals::GetSignalNumber(CString _name)
{
	for(UINT i=0;i<NumberOfSignals;i++)
	{
		if(Name[i]	==	_name)
		{
			return i;
		}
	}
	return -1;
}

int ScenarioSignals::GetTotalSignalDelta(void)
{
	return GraphDeltaY*8 + GetOnlySignalTotalDelta();
}

int ScenarioSignals::GetOnlySignalTotalDelta()
{
	int total = 0;
	for( ULONG i=0; i < NumberOfSignals; i++)
	{
		if(SignalOrder[i]	>=	0)
		{
			total	+=	SignalYSize[i];
		}
	}
	return total;
}

int ScenarioSignals::GetSignalYSize(int i) const
{
    int Result = -1;
    if ( i >= 0 && i < NumberOfSignals )
    {
        Result = SignalYSize[i];
    }
    return Result;
}

int ScenarioSignals::GetGraphDeltaY(void)
{
	return GraphDeltaY;
}

int ScenarioSignals::GetSignalOrder(CString _name)
{
	for( ULONG i=0;i<NumberOfSignals;i++)
	{
		if(Name[i]	==	_name)
		{
			return SignalOrder[i];
		}
	}
	return -1;
}

void ScenarioSignals::RemoveMarksFromSignals( )
{
	for ( ULONG SignalNumber = 0; SignalNumber < NumberOfSignals; SignalNumber++ )
	{
		SignalMarked[ SignalNumber ] = FALSE;
	}
}


void ScenarioSignals::RemoveMarkedSignals(void)
{
	for ( ULONG i = 0; i < NumberOfSignals; i++ )
	{
		if( ( SignalOrder[i] >= 0 )&&(SignalMarked[i] == TRUE) )
		{
			DeleteSignalFromGraph(i);
			SignalMarked[i]	=	FALSE;
		}
	}
}

int ScenarioSignals::GetSignalOrder( int SignalNumber )
{
    int Result = -1;
    if ( SignalNumber >= 0 && SignalNumber < NumberOfSignals )
    {
	    Result = SignalOrder[SignalNumber];
    }
    return Result;
}

int ScenarioSignals::GetSignalPos(int signalnumber) const
{
	if ( signalnumber >= 0 )
	{
		return SignalPos[signalnumber].y;
	}
	else 
	{
		return -1;
	}
}


BOOL ScenarioSignals::IfShowSignal(int SignalNumber)
{
	if ( SignalNumber >= 0 && SignalNumber < NumberOfSignals )
	{
		return (SignalOrder[SignalNumber] >= 0);
	}
	throw WrongSignalNumber();
}

int ScenarioSignals::GetSignalEndPos(int signalnumber)
{
	if ( signalnumber >= 0 )
	{
		return SignalPos[signalnumber].y + SignalYSize[signalnumber];
	}
	else 
	{
		return -1;
	}
}


int ScenarioSignals::GetButtonY(CPoint mpoint)
{
	return GetSignalPos (GetSignalNumber( mpoint ));
}

int ScenarioSignals::DeleteSignalFromGraph(int signalnumber)
{
	int Result = 0;
	if( SignalOrder[signalnumber] < 0 )
	{
		Result = -1;
	}
	else
	{
		PushSignalToEnd(signalnumber);
		SignalOrder[signalnumber]	=	-1;
	}
	return Result;
}

int ScenarioSignals::AddShowSignal(CString _Name)
{
	return AddShowSignal( GetSignalNumber(_Name) );
}

int ScenarioSignals::AddShowSignal( int SignalNumber )
{
	int Result = 0;
	if ( SignalNumber < 0 || SignalOrder[SignalNumber] >= 0 )
	{
		Result = -1;
	}
	else
	{
		int order = 0;
		while ( GetSignalNumber(order) >= 0 )
		{
			order++;
		}
		SignalOrder[SignalNumber]	=	order;
		SignalPos	[SignalNumber].y	=	GetSignalPosByOrder( order );
	}
	return Result;
}

int ScenarioSignals::GetSignalPosByOrder( int order )
{
	return ( order != 0 )? GetSignalEndPos( GetSignalNumber(order-1) ) : 0;
}

int ScenarioSignals::RefreshSignalsStatus(void)
{
	for( ULONG i=0;i<NumberOfSignals;i++)
	{
		if(SignalUsed[i]	==	FALSE)
		{
			PushSignalToEnd(i);
		}
	}
	return 0;
}

void ScenarioSignals::MarkAllSignalsBetween( CPoint MousePoint )
{
	int SignalNumber = GetSignalNumber( MousePoint );
	if ( SignalNumber >= 0 )
	{
		int LastMarkedSignalOrder = -1;
		if ( LastMarkedSignalNumber >= 0 && LastMarkedSignalNumber < NumberOfSignals )
		{
			LastMarkedSignalOrder = GetSignalOrder( LastMarkedSignalNumber );
		}
		if ( LastMarkedSignalOrder < 0 )
		{
			LastMarkedSignalOrder = 0;
			LastMarkedSignalNumber = GetSignalNumber( LastMarkedSignalOrder );
		}
        int SignalOrder = GetSignalOrder( SignalNumber );
		int MinimalSignalOrder = min( SignalOrder, LastMarkedSignalOrder );
		int MaximalSignalOrder = max( SignalOrder, LastMarkedSignalOrder );
		for ( int i = MinimalSignalOrder; i <= MaximalSignalOrder; i++ )
		{
			SignalMarked[ GetSignalNumber( i ) ] = TRUE;
		}
	}
	else
	{
		throw WrongSignalNumber();
	}
}

int ScenarioSignals::PushSignalInColumn(int SourceSignalNumber, CPoint MousePoint )
{
	int TargetSignalNumber = GetSignalNumber( MousePoint );
	int Result = 0;
	if ( TargetSignalNumber == SourceSignalNumber )
	{
		SignalMarked[SourceSignalNumber]	=	!SignalMarked[SourceSignalNumber];
		LastMarkedSignalNumber = SourceSignalNumber;
		Result = -1;
	}
	else
	{
		MoveSignalToPositionOfTargetSignal( SourceSignalNumber, TargetSignalNumber );
	}
	return Result;
}

void ScenarioSignals::MoveSignalToPositionOfTargetSignal(int SourceSignalNumber, 
														 int TargetSignalNumber)
{	
	if( TargetSignalNumber < 0 || TargetSignalNumber >= NumberOfSignals )
	{
		PushSignalToEnd(SourceSignalNumber);
	}
	else
	{
		int step	=	1;
		int button_place	=	SourceSignalNumber;
		int *LowerSignal;
		int *HigherSignal;
		if(SignalOrder[SourceSignalNumber] > SignalOrder[TargetSignalNumber])
		{
			step	=	-step;
			LowerSignal = &SourceSignalNumber;
			HigherSignal = &button_place;
		}
		else
		{
			LowerSignal = &button_place;
			HigherSignal = &SourceSignalNumber;
		}

		int	border			=	SignalOrder[button_place];
		while(SignalOrder[button_place]	!=	SignalOrder[TargetSignalNumber])
		{
			border						+=	step;
			button_place= GetSignalNumber(border);

			SignalPos[*LowerSignal].y	=	SignalPos[*HigherSignal].y;		
			SignalPos[*HigherSignal].y	=	GetSignalEndPos( *LowerSignal );
			SignalOrder[*LowerSignal]--;
			SignalOrder[*HigherSignal]++;
		}
	}
}

void ScenarioSignals::ChangeSignalsPositions( int FirstSignalNumber, int SecondSignalNumber )
{
	if ( SignalOrder[FirstSignalNumber] >= 0 && SignalOrder[SecondSignalNumber] >= 0 )
	{
		int SourceSignalOrder = SignalOrder[FirstSignalNumber];
		MoveSignalToPositionOfTargetSignal( FirstSignalNumber, SecondSignalNumber);
		MoveSignalToPositionOfTargetSignal( SecondSignalNumber, 
											GetSignalNumber( SourceSignalOrder ) );
	}
}

int ScenarioSignals::MoveSignalsInGroup( int SignalNumber, 
										 int OldPositionNumberInGroup, 
										 CPoint CursorPosition )
{
	return MoveSignalsInGroup( SignalNumber, 
							   OldPositionNumberInGroup,
							   GetSignalPositionNumberInGroupFromButtonView( SignalNumber, 
																			 CursorPosition.y ) );
}

int ScenarioSignals::MoveSignalsInGroup( int SignalNumber,
										 int OldPositionNumberInGroup,
										 int NewPositionNumberInGroup )
{
	int Direction = ( (OldPositionNumberInGroup - NewPositionNumberInGroup) < 0)? 1 : -1;
	CArray<int,int> *GroupOfSignals = GetSignalsInGroup( SignalNumber );
	int JumpingSignal = GroupOfSignals->GetAt( OldPositionNumberInGroup );
	for ( int i = OldPositionNumberInGroup; i != NewPositionNumberInGroup; i += Direction )
	{
		GroupOfSignals->SetAt(i, GroupOfSignals->GetAt(i+Direction));
	}
	GroupOfSignals->SetAt( NewPositionNumberInGroup, JumpingSignal);
	return NewPositionNumberInGroup;
}

int ScenarioSignals::PushSignalToEnd(int signalnumber)
{
	if(signalnumber >=0)
	{
		int		order		=	SignalOrder[signalnumber]+1;
		int scanned_place	=	GetSignalNumber(order);
		while(scanned_place	>=	0)
		{
			SignalPos	[scanned_place].y	=	SignalPos[signalnumber].y;		
			SignalOrder[scanned_place]--;
			SignalPos	[signalnumber].y	=	GetSignalEndPos( scanned_place );
			SignalOrder[signalnumber]++;
			order++;
			scanned_place= GetSignalNumber(order);
		}
	}
	return 0;
}

inline int ScenarioSignals::GetSignalIndex( CPoint point )
{
	for( int i = 0; i < NumberOfSignals; i++)
		if ( (SignalPos[i].y <= point.y) && (( GetSignalEndPos(i) )	> point.y ) && ( SignalOrder[i] >= 0 ) )
			return i;
	return -1;
}

int ScenarioSignals::GetSignalNumber(CPoint point)
{
	return GetSignalIndex( point );
}


CString ScenarioSignals::GetSignalName(CPoint point)
{
	int SignalIndex = GetSignalIndex( point );
	return ( SignalIndex >= 0 ) ? GetSignalName(SignalIndex) : "-1";
}

int	ScenarioSignals::GetType	( int SignalNumber)
{
	return Type[ SignalNumber ];
}

void	ScenarioSignals::SetType	( int SignalNumber, int NewType)
{
	Type[ SignalNumber ] = NewType;
}

int ScenarioSignals::GetSignalNumber(int ValidatingSignalOrder)
{
	int Result = -1;
	if ( ValidatingSignalOrder >= 0 )
	{
		for ( ULONG i = 0; i < NumberOfSignals; i++ )
		{
			if( SignalOrder[i] == ValidatingSignalOrder )
			{
				Result = i;
				break;
			}
		}
	}
	return Result;
}

int ScenarioSignals::GetCurrentOrder()
{
	int Order = -1;
	for ( ULONG i = 0; i < NumberOfSignals; i++ )
	{
		if ( Order < SignalOrder[i] )
		{
			Order = SignalOrder[i];
		}
	}
	return Order + 1;
}

void ScenarioSignals::SetRulesForMarkedSignals( unsigned __int64 Min, unsigned __int64 Max, int TypeOfRule )
{
	for ( ULONG i = 0; i < NumberOfSignals; i++ )
	{
		if ( CheckIfSignalMarked( i ) == TRUE )
		{
			Rules[i].Min = Min;
			Rules[i].Max = Max;
			Rules[i].TypeOfRule = TypeOfRule;
		}
	}
}

void ScenarioSignals::DeleteRulesForMarkedSignals()
{
	for ( ULONG i = 0; i < NumberOfSignals; i++ )
	{
		if ( CheckIfSignalMarked( i ) == TRUE )
		{
			Rules[i].Min = -1;
			Rules[i].Max = -1;
			Rules[i].TypeOfRule = RULE_NOT_SET;
		}
	}
}

void ScenarioSignals::SetDefaults(void)
{
	if ( SignalsExist() == FALSE )
	{
		return;
	}
	for( ULONG i=0;i<NumberOfSignals;i++)
	{
		SetDefaultsForSingleSignal( i );
    }
}

void ScenarioSignals::SetDefaultsForSingleSignal( int NumberOfSignal )
{
	Type			[ NumberOfSignal ]		=	SINGLE_SIGNAL_FROM_SCRIPT;
	SignalYSize		[ NumberOfSignal ]		=	GraphDeltaY;
	(*SignalsInGroup	[ NumberOfSignal ]).Add( NumberOfSignal );
	SetDefaultsForSignal( NumberOfSignal );
}

void ScenarioSignals::SetDefaultsForSignal( int NumberOfSignal )
{
	SignalOrder	[NumberOfSignal]		=	GetCurrentOrder();
	SignalPos		[NumberOfSignal].y		=	GetSignalPosByOrder( SignalOrder[NumberOfSignal] );
	SignalMarked	[NumberOfSignal]		=	FALSE;
	SignalBackgroundColor	[NumberOfSignal]		=	WHITE;
}

void ScenarioSignals::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		ar<<NumberOfSignals;
		ar<<GraphDeltaY;
		ar<<Exist;
		for ( ULONG i = 0; i < NumberOfSignals; i++ )
		{
			ar<<Name			[i];
			ar<<OriginalName	[i];
			ar<<SignalOrder	[i];
			ar<<SignalPos		[i];
			ar<<int(SignalsInGroup[i]->GetCount());
			for( int j = 0; j < SignalsInGroup[i]->GetCount(); j++ )
			{
				ar<<(*SignalsInGroup[i])[j];
			}
			ar<<SignalMarked	[i];
			ar<<SignalBackgroundColor	[i];
			ar<<Type[i];
			ar<<SignalYSize[i];
			ar<<Rules[i].Min<<Rules[i].Max<<Rules[i].TypeOfRule;
		}
	}
	else
	{
		int NumberOfSignalsInGroup;
		int SignalNumber;

		ar>>NumberOfSignals;

		if ( TryToCreateArraysOfSignalsData() == false )
		{
			return;
		}

		ar>>GraphDeltaY;
		ar>>Exist;
		for( ULONG i = 0; i < NumberOfSignals; i++ )
		{
			ar>>Name			[i];
			ar>>OriginalName	[i];
			ar>>SignalOrder	[i];
			ar>>SignalPos		[i];
			ar>>NumberOfSignalsInGroup;
			SignalsInGroup[i]->RemoveAll();
			for( int j = 0; j < NumberOfSignalsInGroup; j++ )
			{
				ar>>SignalNumber;
				SignalsInGroup[i]->Add( SignalNumber );
			}
			ar>>SignalMarked	[i];
			ar>>SignalBackgroundColor	[i];
			ar>>Type[i];
			ar>>SignalYSize[i];
			ar>>Rules[i].Min>>Rules[i].Max>>Rules[i].TypeOfRule;
		}
	}
}


int ScenarioSignals::GetNumberOfSignals()
{
	return NumberOfSignals;
}

CArray<int, int> * ScenarioSignals::GetSignalsInGroup( int NumberOfSignal)
{
	return SignalsInGroup[NumberOfSignal];
}

int ScenarioSignals::GetNumberOfShownSignals()
{
	int NumberOfShownSignals = 0;
	int NumberOfSignals = GetNumberOfSignals();
	for ( int i = 0; i < NumberOfSignals; i++ )
	{
		if ( IfShowSignal(i) == TRUE )
		{
			NumberOfShownSignals++;
		}
	}
	return NumberOfShownSignals;
}

int ScenarioSignals::GetDistanceBetweenTwoLinesInGroup()
{
	return (GraphDeltaY - 2*GraphOffsetY) * 2 / YSizeOfSignalDivider;
}

void ScenarioSignals::SetSignalUsed(int signalnumber)
{
	SignalUsed[signalnumber]	=	TRUE;
}

BOOL ScenarioSignals::CheckIfSignalWasUsed(int signalnumber)
{
	return SignalUsed[signalnumber];
}

BOOL ScenarioSignals::CheckIfSignalMarked(int signalnum)
{
	return SignalMarked[signalnum];
}

/*int ScenarioSignals::GetNumberOfMarkedSignals()
{
	int NumberOfSignals = GetNumberOfSignals();
	int NumberOfMarkedSignals = 0;
	for( int i = 0; i < NumberOfSignals; i++ )
	{
		if ( CheckIfSignalMarked( i ) )
		{
			NumberOfMarkedSignals++;
		}
	}
	return NumberOfMarkedSignals;
}*/

/*int ScenarioSignals::AssignSignalToButton(int signalnumber, int buttonnum)
{
	signal_button[signalnumber]	=	buttonnum;
	return 0;
}*/
/*int ScenarioSignals::GetSignalButton(int signalnumber)
{
	return signal_button[signalnumber];
}*/

void ScenarioSignals::WriteToVectorFile(FILE *pFile)
{
	CString fline;
	for( ULONG i = 0; i<NumberOfSignals; i++ )
	{
		if(	SignalUsed[i]	==	TRUE)
		{
			fline += OriginalName[i]+" ";
		}
	}
	fline	+="\n";
	myfputs(fline,pFile);
}

void ScenarioSignals::SetSignalBackgroundColor( COLORREF Color, int SignalPos )
{
	SignalBackgroundColor[SignalPos] = Color;
}

COLORREF ScenarioSignals::GetSignalBackgroundColor( int SignalPos )
{
	return SignalBackgroundColor[SignalPos];
}

void ScenarioSignals::OnSortSelectedWavesByName()
{
	std::vector<int> SelectedWaves, OrdersOfSelectedWaves;
	GetSelectedWaves( SelectedWaves );
	int NumberOfSelectedWaves = SelectedWaves.size();
	for ( int i = 0; i < NumberOfSelectedWaves; i++ )
	{
		OrdersOfSelectedWaves.push_back( SignalOrder[SelectedWaves[i]] );
	}
	SortSelectedWavesByName( SelectedWaves );

	//Sorting orders for comparison with sorted waves by name later
	std::sort( OrdersOfSelectedWaves.begin(), OrdersOfSelectedWaves.end() );
	for ( int i = 0; i < NumberOfSelectedWaves; i++ )
	{
		ChangeSignalsPositions( SelectedWaves[i], GetSignalNumber( OrdersOfSelectedWaves[i] ) );
	}
}

void ScenarioSignals::GetSelectedWaves( std::vector<int> &SelectedWaves )
{
	for ( int NumberOfSignal = GetFirstMarkedSignal();
		  NumberOfSignal >= 0;
		  NumberOfSignal = GetNextMarkedSignal( NumberOfSignal ) 
		)
	{
		SelectedWaves.push_back( NumberOfSignal );
	}
}

void ScenarioSignals::SortSelectedWavesByName( std::vector<int> &SelectedWaves )
{
	if ( *std::max_element( SelectedWaves.begin(), SelectedWaves.end() ) >= NumberOfSignals )
	{
		throw InvalidArray();
	}
	std::vector<SignalForSort> SignalsForSort;
	SignalForSort Temp;
	int SizeOfArray = SelectedWaves.size();
	for ( int i = 0; i < SizeOfArray; i++ )
	{
		Temp.SignalNumber = SelectedWaves[i];
		Temp.Name = GetOriginalName( Temp.SignalNumber );
		SignalsForSort.push_back( Temp );
	}
	std::sort( SignalsForSort.begin(), SignalsForSort.end() );
	for ( int i = 0; i < SizeOfArray; i++ )
	{
		SelectedWaves[i] = SignalsForSort[i].SignalNumber;
	}
}

int ScenarioSignals::GetMinPositionOfMarkedSignals()
{
	int Size = GetNumberOfSignals();
    unsigned int Min = static_cast<unsigned int>(-1);
	for( size_t i = 0; i < Size; i++)
		if (SignalMarked[i] == TRUE && SignalPos[i].y <= Min )
			Min = SignalPos[i].y;
	return static_cast<int>(Min);
}

bool ScenarioSignals::MoreThanOneMarked()
{
	int Count(0), Size = GetNumberOfSignals();
	for(int i = 1; i < Size; i++)
	{
		if (SignalMarked[i] == TRUE)
		{
			Count++;
			if ( Count == 2 )
				return true;
		}
	}
	return false;
}

int ScenarioSignals::GetFirstMarkedSignal()
{
	return GetNextMarkedSignal( -1 );
}

int ScenarioSignals::GetMinYMarkedSignal()
{
	int Min = 0x7FFFFFFF , Result( -1 );
	for ( int i = 0 ; i < NumberOfSignals ; i++)
	{
		if ( SignalMarked[i] == TRUE && SignalPos[i].y < Min )
		{
			Min = SignalPos[i].y;
			Result = i;
		}
	}

	return Result;
}


int ScenarioSignals::GetNextMarkedSignal( int StartPositionOfSearch )
{
	for ( int i = StartPositionOfSearch + 1; i < NumberOfSignals; i++ )
	{
		if ( SignalMarked[i] == TRUE )
		{
			return i;
		}
	}
	return -1;
}

//////////////////////////////////////////////////////////////////////
// StringToGroupsSequences Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

StringToGroupsSequences::StringToGroupsSequences()
{
	numberofgroups	=	0;
}

StringToGroupsSequences::~StringToGroupsSequences()
{

}

int StringToGroupsSequences::LoadExpression(CString expression)
{
	CString		leftpart;
	CString		rightpart;
	CString		tail;
	int			pos[4];
	numberofgroups	=	0;
	tail			=	expression;
	while(tail.GetLength()	 >	0)
	{
		pos[0]	=	tail.Find('+',0);	
		if(pos[0]	==	-1)
		{
			leftpart	=	tail;
			rightpart	=	"";
		}
		else
		{
			leftpart	=	tail.Left(pos[0]);
			rightpart	=	tail.Mid(pos[0]+1);
			pos[2]	=	rightpart.FindOneOf("qwertyuiopasdfghjklzxcvbnm");
			if(pos[2]<0)
			{
				rightpart.Delete(0,rightpart.GetLength());
			}
		}
		tail	=	rightpart;
		
		
		pos[1]		=	leftpart.Find('*',0);
		if(pos[1]	==	-1)
		{
			groups[numberofgroups]				=	leftpart;
			numberofsequnces[numberofgroups]	=	1;
			numberofgroups++;
		}
		else
		{
			CString param[2];
			param[0]		=	leftpart.Left(pos[1]);
			param[1]		=	leftpart.Mid(pos[1]+1);
			int		number	=	atoi((LPCTSTR) param[0]);
			if(number	>	0)
			{
					groups[numberofgroups]					=	param[1];
					groups[numberofgroups].Replace("\t ","");
					numberofsequnces[numberofgroups]		=	number;
			}
			else
			{
					number	=	atoi((LPCTSTR) param[1]);
					groups[numberofgroups]					=	param[0];
					groups[numberofgroups].Replace("\t ","");
					numberofsequnces[numberofgroups]		=	number;
			}
			numberofgroups++;
		}
	}
	
	if(numberofgroups	==	0)
	{
		return -1;
	}
	return 0;
}


//////////////////////////////////////////////////////////////////////
// wavesignal Class
//////////////////////////////////////////////////////////////////////

void wavesignal::ExportInfo()
{
}

wavesignal::~wavesignal()
{
	changes.RemoveAll();
	Comments.RemoveAll();
}

DWORD wavesignal::WriteComponentToGraphData( graphdata* graph, 
											 unsigned __int64 startposition, 
											 unsigned __int64 offset,
											 unsigned __int64 delta,
											 unsigned __int64 length,
											 int TimeDivider,
											 WORD signalID,
											 HighlightingRule Rule)
{
	return 0;
}

wavesignal::wavesignal(mymessages	*_StatusList)
{
	StatusList		=	_StatusList;
}

CString wavesignal::GetName() throw()
{
	return name;
}

void wavesignal::SetSignalType( int NewType )
{
	type	=	NewType;
}

int wavesignal::GetSignalType()
{
	return type;
}

void wavesignal::SetName(CString _name)
{
	name	=	_name;
}

void wavesignal::MarkIncludedChanges( Signal CurrentSignal, bool **MarksForSignals, int NumberOfSignal )
{
	__int64 GlobalTime = 0;
	for ( int k = 1, l = 0; k < changes.GetCount(); k++ )
	{
		GlobalTime += changes[k];
		for ( ; l < CurrentSignal.Changes.GetCount(); l++ )
		{
			if ( GlobalTime == CurrentSignal.Changes[l] && MarksForSignals[NumberOfSignal][l] != true )
			{
				MarksForSignals[NumberOfSignal][l] = true;
				l++;
				break;
			}
			else if ( CurrentSignal.Changes[l] > GlobalTime )
			{
				break;
			}
		}
	}
}

unsigned __int64 wavesignal::GetFirstTimingChangeAfterTime( unsigned __int64 TimeLimit )
{
	if ( this != NULL )
	{
		__int64 TotalTime = 0;
		int i = 0;
		while ( i < changes.GetCount() )
		{
			if ( changes[i] < 0 )
			{
				int k;
				for ( __int64 j = 0 ; j > changes[i] ; j--)
				{
					for ( k = i+1 ; ( k < changes.GetCount() ) && ( changes[k] >= 0 ) ; k++ )
					{
						TotalTime += changes[k];
						if ( TotalTime >= TimeLimit )
							return TotalTime;
					}
				}
				i = k;
			}
			else
			{
				TotalTime += changes[i];
				if ( TotalTime >= TimeLimit )
					return TotalTime;
				i++;
			}
		}
		return -1;
	}
	throw WrongTypeOfWavesignal();
}

unsigned __int64 GroupOfWavesignals::GetFirstTimingChangeAfterTime(unsigned __int64 TimeLimit )
{
	unsigned __int64 TimeOfCurrentSignal, Min;
	Min = IncludedSignals[0]->GetFirstTimingChangeAfterTime( TimeLimit );
	for (int i = 1 ; i < NumberOfSignals ; i++)
	{
		TimeOfCurrentSignal = IncludedSignals[i]->GetFirstTimingChangeAfterTime( TimeLimit );
		if ( TimeOfCurrentSignal == -1 )
			continue;
		if ( Min == -1 || TimeOfCurrentSignal < Min )
			Min = TimeOfCurrentSignal;
	}
	return Min;
}

void wavesignal::SetFirstTimingChange( unsigned __int64 NewValue)
{
	if ( this != NULL )
	{
		for ( int i = 0; i < changes.GetCount(); i++ )
		{
			if ( changes[i] >= 0)
			{
				changes[i] = NewValue;
				return;
			}
		}
	}
	throw WrongTypeOfWavesignal();
}

//////////////////////////////////////////////////////////////////////
// GroupOfWavesignals Class
//////////////////////////////////////////////////////////////////////


GroupOfWavesignals::GroupOfWavesignals(mymessages	*_StatusList) :wavesignal( _StatusList )
{
	type			=	W_GROUP;
	NumberOfSignals = 0;
	IncludedSignals = NULL;
}

GroupOfWavesignals::~GroupOfWavesignals()
{
	delete[] IncludedSignals;
}

void GroupOfWavesignals::AddWavesignalsFromArray( CArray<SimpleWavesignal*, SimpleWavesignal*> *Wavesignals )
{
	NumberOfSignals = Wavesignals->GetCount();
	delete[] IncludedSignals;
	IncludedSignals = new SimpleWavesignal*[NumberOfSignals];
	for (int i = 0; i < NumberOfSignals; i++ )
	{
		IncludedSignals[i] = (*Wavesignals)[i];
	}
}

int GroupOfWavesignals::GetNumberOfSignals()
{
	return NumberOfSignals;
}

SimpleWavesignal* GroupOfWavesignals::GetWavesignal( int Index )
{
	return IncludedSignals[Index];
}

void GroupOfWavesignals::FillDataOfWavesignalGroup( CString NameOfWavesignalsGroup, int SignalNumber, simple_group* ChosenGroup )
{
	CArray<SimpleWavesignal*, SimpleWavesignal*> ChosenSignals;
	SetName( NameOfWavesignalsGroup );
	ChosenGroup->FillArrayOfWaveSignalsByNamesOfIncludedSignals( &ChosenSignals, SignalNumber );
	AddWavesignalsFromArray( &ChosenSignals );
	SetChangesFromIncludedSignals( ChosenGroup->GetClock() );
}

void GroupOfWavesignals::SetChangesFromIncludedSignals( __int64 length )
{
	CArray<__int64,__int64> **Changes = new CArray<__int64,__int64>*[NumberOfSignals];
	for( int i = 0; i < NumberOfSignals; i++ )
	{
		Changes[i] = new CArray<__int64,__int64>();
		IncludedSignals[i]->GetAbsoluteChanges( Changes[i], length );
	}
	CreateChangesFromArray( Changes );
	for( int i = 0; i < NumberOfSignals; i++ )
	{
		Changes[i]->RemoveAll();
		delete Changes[i];
	}
	delete[] Changes;
}

void GroupOfWavesignals::CreateChangesFromArray( CArray<__int64,__int64> **Changes )
{
	long *Index = new long[NumberOfSignals];
	int SignalsLeft = NumberOfSignals;
	for ( int i = 0; i < NumberOfSignals; i++ )
	{
		if ( Changes[i]->GetCount() < 1 )
		{
			Index[i] = -1;
			SignalsLeft--;
		}
		else
		{
			Index[i] = 0;
		}
	}
	unsigned __int64 PreviousValue = 0;
	unsigned __int64 Min;
	int MinIndex;
	while ( SignalsLeft > 0 )
	{
		Min = -1;
		for( int i = 0; i < NumberOfSignals; i++ )
		{
			if ( Index[i] >= 0 && Min > (*Changes[i])[Index[i]] )
			{
				Min = (*Changes[i])[Index[i]];
				MinIndex = i;
			}
		}
		changes.Add( Min - PreviousValue );
		PreviousValue = Min;
		Index[MinIndex]++;
		if ( Index[MinIndex] == Changes[MinIndex]->GetCount() )
		{
			Index[MinIndex] = -1;
			SignalsLeft--;
		}
	}
	delete[] Index;
}

DWORD GroupOfWavesignals::WriteComponentToGraphData( graphdata* graph, 
													 unsigned __int64 startposition, 
													 unsigned __int64 offset,
													 unsigned __int64 delta,
													 unsigned __int64 length,
													 int TimeDivider,
													 WORD signalID,
													 HighlightingRule Rule)
{
	unsigned __int64 bitoffset = 0;
	BOOL lastbitvalue = 0;
	graph->PutSignalInGraph(0,startposition,signalID,HighlightingRule());
	for ( int i = 0; i < changes.GetCount() && bitoffset <= length; i++ )
	{
		bitoffset		+=	changes[i]/TimeDivider;
		lastbitvalue = (lastbitvalue+1)%2;
		graph->PutSignalInGraph(lastbitvalue,bitoffset+startposition,signalID,Rule);
	}
	return 0;
}

//////////////////////////////////////////////////////////////////////
// SimpleWavesignal Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

SimpleWavesignal::SimpleWavesignal(mymessages	*_StatusList) :wavesignal( _StatusList )
{
	number_in_file	=	-1;
	firststatus		=	0;
	type			=	W_CONST;
}

SimpleWavesignal::SimpleWavesignal( mymessages	*_StatusList, const Signal &Sig ) :wavesignal( _StatusList )
{
	name = Sig.Name;
	type	=	W_PWM;
	firststatus = Sig.FirstStatus;
	changes.Add( -1 );
	Comments.Add( "" );   
	for ( int i = 0; i < Sig.Changes.GetSize(); i++ )
	{
		changes.Add( Sig.Changes[i] );
		Comments.Add( Sig.Comments[i] );
	}
	number_in_file	=	-1;
	type			=	W_PWM;
}

SimpleWavesignal::~SimpleWavesignal()
{
}

void SimpleWavesignal::GetAbsoluteChanges( CArray<__int64,__int64> *Changes, unsigned __int64 length )
{
	if ( this == NULL )
	{
		return;
	}
	long size	=	changes.GetSize();
	if(size	<=	0)
	{
		return;
	}

	if(changes[0] >=0 )
	{
		numofdeltas	=	1;	
		deltaoffset	=	0;
	}
	else
	{
		numofdeltas	=	(ULONG)-changes[0];	
		deltaoffset	=	1;
	}
	ciclenumber	=	1;
	cicleoffset	=	0;
	bitoffset	=	0;

	while( bitoffset <= length)
	{
		if(changes[deltaoffset] >= 0)
		{
			bitoffset		+=	changes[deltaoffset];
			Changes->Add( bitoffset );
			deltaoffset	++;
		}

		if(deltaoffset	>= size)
		{
			if( numofdeltas > ciclenumber )
			{
				deltaoffset		=	cicleoffset+1;
				ciclenumber++;
			}
			else
			{
				return;
			}
		}

		if(changes[deltaoffset] < 0)
		{
			if(numofdeltas > ciclenumber)
			{
				ciclenumber		++;
			}
			else
			{
				numofdeltas		=	(ULONG)-changes[deltaoffset];
				ciclenumber		=	1;
				cicleoffset		=	deltaoffset;
			}
			deltaoffset	=	1+cicleoffset;
		}
	}
}

__int64 SimpleWavesignal::GetInterval( __int64 Point, __int64 TimeTopLimit ,CString *outComment )
{
	long size	=	changes.GetSize();
	if((size <= 0) || ( Point < 0))
		return -1;
	
	ULONG CicleNumber	=	1;
	ULONG CicleOffset	=	0;
	unsigned __int64 BitOffset = 0;
	ULONG NumofDeltas;
	ULONG DeltaOffset;

	if(changes[0] >=0 )
	{
		NumofDeltas	= 1;	
		DeltaOffset	= 0;
	}
	else
	{
		NumofDeltas	= (ULONG)-changes[0];	
		DeltaOffset	= 1;
	}
	ULONG OldDeltaOffset = DeltaOffset;

	while( BitOffset <= Point )
	{
		if(changes[DeltaOffset] >= 0)
		{
			BitOffset += changes[DeltaOffset];
			OldDeltaOffset = DeltaOffset;
			DeltaOffset	++;
		}

		if(DeltaOffset	>= size)
			if( NumofDeltas > CicleNumber )
			{
				DeltaOffset		=	CicleOffset + 1;
				CicleNumber++;
			}
			else 	
			{
				if ( outComment != NULL )
					*outComment =  Comments.IsEmpty() ? "" : Comments[OldDeltaOffset];
				return ( BitOffset > Point ) ? changes[OldDeltaOffset] : ( TimeTopLimit - BitOffset );
			}
		

		if(changes[DeltaOffset] < 0)
		{
			if(NumofDeltas > CicleNumber)
				CicleNumber ++;
			else
			{
				NumofDeltas		=	(ULONG)-changes[DeltaOffset];
				CicleNumber		=	1;
				CicleOffset		=	DeltaOffset;
			}
			DeltaOffset	= CicleOffset + 1;
		}
	}
	if ( outComment != NULL )
		*outComment =  Comments.IsEmpty() ? "" : Comments[OldDeltaOffset];
	return changes[OldDeltaOffset]; 
}

int SimpleWavesignal::uploadstring(CString command, CString OriginalLine)
{
	int pos[5];
	pos[0]	=	command.Find("file",0);
	if((pos[0] >= 0)||(command.GetLength()<3))
	{
		return -1;
	}

	pos[0]	=	OriginalLine.Find("SIGNAL",0);
	if(pos[0] == -1) return -1;

	pos[1]	=	OriginalLine.Find(' ',pos[0]);
	pos[2]	=	OriginalLine.ReverseFind('=');
	/*int Temp=	line.Find(' ',pos[1]+1);
	if(Temp < pos[2])
	{
		pos[2]	=	Temp;
	}*/
	name	=	OriginalLine.Mid(pos[1]+1,pos[2]-pos[1]-1);
	name.Trim();
//  Code for signal =	const	
	if((pos[3]	=	command.Find("const",0))	>	-1)
	{
		type	=	W_CONST;
		pos[4]	=	command.Find(' ',pos[3]+1);
		if(pos[4] <0)
		{
			return -1;
		}
		if(command[pos[4]+1] == '0')
		{
			firststatus	=	0;
		}
		else
		{
			firststatus	=	1;
		}
		return 0;
	}

//  Code for signal =	clk	
	if((pos[3]	=	command.Find("clk",0))	>	-1)
	{
		CString _line = command;
		type	=	W_CLK;
		pos[4]	=	command.Find(' ',pos[3]+1);
		if(pos[4] <0)
		{
			return -1;
		}
		_line	=	_line.Mid(pos[4]+1);
		if(_line[0] == '0')
		{
			firststatus	=	0;
		}
		else
		{
			firststatus	=	1;
		}
		_line	=	_line.Mid(2);
		CString strnum;
		int		num	;
		while(0 < _line.GetLength())
		{
			pos[0]	=	_line.Find(' ',0);
			if(pos[0] <0)
			{
				strnum		=	_line;
				_line		=	"";
			}
			else
			{
				strnum	=	_line.Left(pos[0]);
				_line	=	_line.Mid(pos[0]+1);
				
			}
			num		=	atol((LPCTSTR) strnum);
			if(num	!= 0)
			{
				changes.Add(num);
			}
		}
		if(changes.GetSize() < 2)
		{
			return -1;
		}
		return 0;
	}
	
//  Code for signal =	pwm	
	if((pos[3]	=	command.Find("pwm",0))	>	-1)
	{
		CString _line = command;
		type	=	W_PWM;
		pos[4]	=	command.Find(' ',pos[3]+1);
		if(pos[4] <0)
		{
			return -1;
		}
		_line	=	_line.Mid(pos[4]+1);
		if(_line[0] == '0')
		{
			firststatus	=	0;
		}
		else
		{
			firststatus	=	1;
		}
		_line	=	_line.Mid(2);
		CString strnum;
		int		num	;
		while(0 < _line.GetLength())
		{
			pos[0]	=	_line.Find(' ',0);
			if(pos[0] <0)
			{
				strnum		=	_line;
				_line		=	"";
			}
			else
			{
				strnum	=	_line.Left(pos[0]);
				_line	=	_line.Mid(pos[0]+1);
				
			}
			num		=	atol((LPCTSTR) strnum);

			changes.Add(num);
		}
		if(changes.GetSize() < 2)
		{
			return -1;
		}
		return 0;
	}
	
	return -1;
}

void SimpleWavesignal::SetNumberInFile(int _number)
{
	number_in_file	=	_number;
}



int SimpleWavesignal::GetNumberInFile()
{
	return number_in_file;
}

void SimpleWavesignal::ResetProccess()
{
	readingvalues	=	FALSE;
	bitoffset		=	1;

}
void SimpleWavesignal::SetFirstValues()
{
	readingvalues	=	FALSE;
	bitoffset		=	1;
}

void SimpleWavesignal::AddBit(BYTE _value, unsigned __int64 newabsoluteoffset)
{
	if(readingvalues	==	FALSE)
	{
		readingvalues	=	TRUE;
		firststatus		=	_value;
		changes.Add(-1);
		lastbitvalue	=	_value;
		absoluteoffset	=	newabsoluteoffset;
		return ;
	}
	bitoffset		+=	(WORD)(newabsoluteoffset - absoluteoffset);
	absoluteoffset	=	newabsoluteoffset;
	if(_value	==	lastbitvalue)
	{
		return;
	}
	changes.Add(bitoffset-1);
	lastbitvalue	=	_value;
	bitoffset		=	1;
}







char SimpleWavesignal::GetCLKBitName()
{
	if(readingvalues	==	FALSE)
	{
		readingvalues	=	TRUE;
		lastbitvalue	=	firststatus;
		bitoffset		=	0;
		deltaoffset		=	0;
		if(firststatus == 0)return '0';else	return '1';
	}
	

	bitoffset++;
	if( bitoffset	>=	changes[deltaoffset])
	{
		bitoffset	=	0;
		if( deltaoffset == 0 )  deltaoffset	=	1;else deltaoffset	=	0;
		if(lastbitvalue == 0)  lastbitvalue	=	1;else lastbitvalue	=	0;
	}
	if(lastbitvalue == 0) return '0';else return '1';
}

BYTE SimpleWavesignal::GetCLKBit()
{
	if(readingvalues	==	FALSE)
	{
		readingvalues	=	TRUE;
		lastbitvalue	=	firststatus;
		bitoffset		=	0;
		deltaoffset		=	0;
		return firststatus;
	}
	
	bitoffset++;
	if(bitoffset	>=	changes[deltaoffset])
	{
		bitoffset	=	0;
		if(deltaoffset	== 0)  deltaoffset	=	1;else deltaoffset	=	0;
		if(lastbitvalue == 0)  lastbitvalue	=	1;else lastbitvalue	=	0;
	}
	return lastbitvalue;
}



char SimpleWavesignal::GetPWMBitName()
{
	static int NewSize = 0;
	NewSize++;
	if(readingvalues	==	FALSE)
	{
		readingvalues	=	TRUE;
		lastbitvalue	=	firststatus;
		deltaoffset		=	1;
		numofdeltas		=	1;
		bitoffset		=	0;
		ciclenumber		=	cicleoffset	=	0;
		if(firststatus == 0)return '0';else	return '1';
	}
	if((-changes[ciclenumber])<0)
	{
		return 0;
	}
	
	
	bitoffset++;
	DWORD size	=	changes.GetSize()-1;
	if(size	==	0)
	{
		if(firststatus == 0)return '0';else	return '1';
	}
	if((deltaoffset	>= size)&&(bitoffset	>=	changes[deltaoffset])&&(numofdeltas < (-changes[ciclenumber])))
	{
		bitoffset	=	0;
		deltaoffset	=	1+cicleoffset;
		numofdeltas	++;
		if(lastbitvalue == 0) lastbitvalue	=	1;else lastbitvalue	=	0;
	}

	if((deltaoffset	<= size)&&(bitoffset	>=	changes[deltaoffset]))
	{
		bitoffset	=	0;
		deltaoffset	++;
		if(lastbitvalue == 0) lastbitvalue	=	1;else lastbitvalue	=	0;
	}
//---------------------------------------------------------------------------------
	if(changes[deltaoffset] < 0)
	{
		if(numofdeltas >= (-changes[ciclenumber]))
		{
			ciclenumber	=	deltaoffset;
			cicleoffset	=	ciclenumber;
			numofdeltas	=	1;
			bitoffset	=	0;
		}
		else
		{
			numofdeltas++;
			bitoffset	=	0;
		}
		
		deltaoffset	=	1+cicleoffset;
	}
//-----------------------------------------------------------------------------------
	if(lastbitvalue == 0) return '0';else return '1';
}

BYTE SimpleWavesignal::GetPWMBit()
{
	if(readingvalues	==	FALSE)
	{
		readingvalues	=	TRUE;
		lastbitvalue	=	firststatus;
		deltaoffset		=	1;
		numofdeltas		=	1;
		bitoffset		=	0;
		ciclenumber		=	0;
		cicleoffset		=	0;
		return firststatus;
	}
	if((-changes[ciclenumber])<0)
	{
		return 0;
	}
	
	
	bitoffset++;
	long size	=	changes.GetSize()-1;
	if(size	==	0)
	{
		return firststatus;
	}
	


	if((deltaoffset	>= size)&&(bitoffset	>=	changes[deltaoffset])&&(numofdeltas < (-changes[ciclenumber])))
	{
		bitoffset	=	0;
		deltaoffset	=	1+cicleoffset;
		numofdeltas	++;
		if(lastbitvalue == 0) lastbitvalue	=	1;else lastbitvalue	=	0;
	}


	if((deltaoffset	<= size)&&(bitoffset	>=	changes[deltaoffset]))
	{
		bitoffset	=	0;
		deltaoffset	++;
		if(lastbitvalue == 0) lastbitvalue	=	1;else lastbitvalue	=	0;
	}

	if(changes[deltaoffset] < 0)
	{
		if(numofdeltas >= (-changes[ciclenumber]))
		{
			ciclenumber	=	deltaoffset;
			cicleoffset	=	ciclenumber;
			numofdeltas	=	1;
			bitoffset	=	0;
		}
		else
		{
			numofdeltas++;
			bitoffset	=	0;
		}
		
		deltaoffset	=	1+cicleoffset;
	}
	return lastbitvalue;
}









void SimpleWavesignal::ExportInfo()
{
	switch(type)
	{
	case	W_CONST:
					{
						StatusList->AddMessage("Signal = "+name+"  type  CONST ="+Long64ToCString((__int64)firststatus));
					};break;
	case	W_CLK:
					{
						if(changes.GetSize()<2)
						{
							StatusList->AddMessage("ERROR:Signal = "+name+"  type  CLK   = Incorrect format");
						}
						else
						{
							StatusList->AddMessage("Signal = "+name+"  type  CLK   ="+
											Long64ToCString((__int64)firststatus)+" "+
											Long64ToCString(changes[0])+" "+
											Long64ToCString(changes[1]));
						}
					};break;
	case	W_PWM:
					{
						if(changes.GetSize()<1)
						{
							StatusList->AddMessage("ERROR:Signal = "+name+"  type  PWM   = Incorrect format");
						}
						else
						{
							CString param	=	" "+Long64ToCString(firststatus)+ " "+Long64ToCString(changes[0]);
							for(int i=1;i<changes.GetSize();i++)
							{
								param += " "+Long64ToCString(changes[i]);
							}
							StatusList->AddMessage("Signal = "+name+"  type  PWM   ="+param);
						}
					};break;
	case	W_PWM_FILE:
					{
						if(changes.GetSize()<1)
						{
							StatusList->AddMessage("ERROR:Signal = "+name+"  type  PWM_FILE   = Incorrect format");
						}
						else
						{
							CString param	=	" "+Long64ToCString(firststatus)+ " "+Long64ToCString(changes[0]);
							for(int i=1;i<changes.GetSize();i++)
							{
								param += " "+Long64ToCString(changes[i]);
							}
							StatusList->AddMessage("Signal = "+name+"  type  PWM_FILE   ="+param);
						}
					};break;
	}
}

char SimpleWavesignal::GetBitName()
{
	char 	number = char('0'+firststatus);
	switch(type)
	{
	case	W_CLK:
					{
						return GetCLKBitName();
					};break;
	case	W_PWM:
					{
						return GetPWMBitName();
					};break;
	case	W_PWM_FILE:
					{
						return GetPWMBitName();
					};break;
	}
	
	
	return number;
}

BYTE SimpleWavesignal::GetBit()
{
	int		number	=	firststatus;
	switch(type)
	{
	case	W_CLK:
					{
						return GetCLKBit();
					};break;
	case	W_PWM:
					{
						return GetPWMBit();
					};break;
	case	W_PWM_FILE:
					{
						return GetPWMBit();
					};break;
	}
	return number;
}


DWORD SimpleWavesignal::WriteConstToGraphData(graphdata* graph, 
										unsigned __int64 startposition, 
										unsigned __int64 offset,
										unsigned __int64 length,
										int TimeDivider,
										WORD signalID,
										HighlightingRule Rule)
{
//	for(DWORD i=0;i<=graph->graphdelta;i++)
//	{
//		if(	(graph->signals_cut_x[i]	>=startposition)&&
//			(graph->signals_cut_x[i]	<=startposition+length))
//		{
//			graph->signals_status[i].sig[signalID]	=	firststatus;
//		}
//	}
	graph->PutSignalInGraph(firststatus,startposition/TimeDivider,signalID,HighlightingRule());
	//graph->PutSignalInGraph(firststatus,startposition+length,signalID, (length == IntervalCompare( length, Rule.Min, Rule.Max ))?true:false );
	return 0;
}




DWORD SimpleWavesignal::WriteClkToGraphData(	graphdata* graph, 
										unsigned __int64 startposition, 
										unsigned __int64 offset,
										unsigned __int64 length,
										int TimeDivider,
										WORD signalID,
										HighlightingRule Rule)
{
//-----------------------------------------------------------------------------------------------
	lastbitvalue	=	firststatus;
	bitoffset		=	0;
	deltaoffset		=	0;
	graph->PutSignalInGraph(lastbitvalue,(startposition+bitoffset)/TimeDivider,signalID,HighlightingRule());
	while(bitoffset <= length)
	{
		bitoffset	+=changes[deltaoffset];
		if(deltaoffset	== 0)  deltaoffset	=	1;else deltaoffset	=	0;
		if(lastbitvalue == 0)  lastbitvalue	=	1;else lastbitvalue	=	0;
		graph->PutSignalInGraph(lastbitvalue,(startposition+bitoffset)/TimeDivider,signalID,Rule);
	}
	return 0;
}


DWORD SimpleWavesignal::WritePWMToGraphData(	graphdata* graph, 
										unsigned __int64 startposition, 
										unsigned __int64 offset,
										unsigned __int64 delta,
										unsigned __int64 length,
										int TimeDivider,
										WORD signalID,
										HighlightingRule Rule)
{
	unsigned __int64 GlobalPosition;
	unsigned __int64 OldGlobalPosition = startposition/TimeDivider;
	bool FirstTime = true;
	if ( OldGlobalPosition >= offset && OldGlobalPosition <= offset + delta )
	{
		FirstTime = false;
		graph->PutSignalInGraph( firststatus, OldGlobalPosition, signalID, ( OldGlobalPosition == 0 )? HighlightingRule() : Rule );
	}
	if(changes[0] >=0 )
	{
		return 0;
	}
	else
	{
		numofdeltas	=	(ULONG)-changes[0];	
		lastbitvalue=	firststatus;
		bitoffset	=	0;
		deltaoffset	=	1;
		ciclenumber	=	1;
		cicleoffset	=	0;
	}
	
	long size	=	changes.GetSize();
	if(size	<=	0)
	{
		return 0;
	}
	while(bitoffset <= length)
	{
		// This TRY is made for checking out the negative value in the end of any signal's string.
		TRY
		{
			if(changes[deltaoffset] >= 0)
			{
				bitoffset		+=	changes[deltaoffset];
				GlobalPosition = (bitoffset + startposition)/TimeDivider;
				lastbitvalue = !lastbitvalue;
				if ( GlobalPosition >= offset && GlobalPosition <= offset + delta )
				{
					if ( FirstTime == true )
					{
						FirstTime = false;
						graph->PutSignalInGraph( !lastbitvalue, OldGlobalPosition, signalID, HighlightingRule() );
					}
					graph->PutSignalInGraph( lastbitvalue, GlobalPosition, signalID, Rule );
				}
				else if ( GlobalPosition < offset )
				{
					OldGlobalPosition = GlobalPosition;
				}
				else
				{
					graph->PutSignalInGraph( lastbitvalue, GlobalPosition, signalID, Rule );
					lastbitvalue = !lastbitvalue;
					break;
				}
				deltaoffset	++;
			}
		}
		// If index (deltaoffset) is out of arrays range, the exception will be detected.
		CATCH ( CInvalidArgException, e )
		{
			char num [ 10 ];
			_i64toa( changes[deltaoffset-1], num, 10 );
			CString snum = num;
			//Negative value in the last cell of the array will be shown and the name of the proper signal.  
			StatusList->AddMessage( "ERROR: Input data in the script file (*.SRP) is corrupted. Value " + snum + " is invalid in the field of signal: "+'"'+ name +'"' );
			
			// Incorrect value will be replaced by positive one and graph will be invariable up to the end of his range.
			deltaoffset --;
			changes[deltaoffset] = length - bitoffset;
			e->Delete();
			return 0;
		}
		END_CATCH

		if(deltaoffset	>= size)
		{
			if(numofdeltas > ciclenumber)
			{
				deltaoffset		=	cicleoffset+1;
				ciclenumber++;
			}
			else
			{
				break;
			}
		}
		if(changes[deltaoffset] < 0)
		{
			if(numofdeltas > ciclenumber)
			{
				ciclenumber		++;
			}
			else
			{
				numofdeltas		=	(ULONG)-changes[deltaoffset];
				ciclenumber		=	1;
				cicleoffset		=	deltaoffset;
			}
			deltaoffset	=	1+cicleoffset;
		}
	}
	if ( FirstTime == true )
	{
		graph->PutSignalInGraph( lastbitvalue, OldGlobalPosition, signalID, HighlightingRule() );
	}
	return 0;
}

DWORD SimpleWavesignal::WriteComponentToGraphData(	graphdata* graph, 
												unsigned __int64 startposition, 
												unsigned __int64 offset,
												unsigned __int64 delta,
												unsigned __int64 length,
												int TimeDivider,
												WORD signalID,
												HighlightingRule Rule)
{
	switch(type)
	{
	case	W_CLK		:
					{
						return WriteClkToGraphData(graph,startposition,offset,length, TimeDivider, signalID,Rule);
					};break;
	case	W_PWM		:
					{
						DWORD res	=	WritePWMToGraphData(graph,startposition,offset, delta, length, TimeDivider,signalID,Rule);
						if(res == -1)
						{
							res	=	WriteConstToGraphData(graph,startposition,offset,length, TimeDivider,signalID,Rule);
						}
						return res;
					};break;
	case	W_PWM_FILE	:
					{
						DWORD res	=	WritePWMToGraphData(graph,startposition,offset, delta, length, TimeDivider,signalID,Rule);
						if(res == -1)
						{
							res	=	WriteConstToGraphData(graph,startposition,offset,length, TimeDivider,signalID,Rule);
						}
						return res;
					};break;
	default				:	
					{
						return WriteConstToGraphData(graph,startposition,offset,length, TimeDivider,signalID,Rule);
					};break;
	}
	return 0;
}

void SimpleWavesignal::ComputeSignalStatistics( __int64 TotalTime )
{
	__int64 Maximum[2];
	Maximum[0] = Maximum[1] = 0;
	__int64 Minimum[2];
	Minimum[0] = Minimum[1] = TotalTime;
	unsigned __int64 SumForMean[2];
	SumForMean[0] = SumForMean[1] = 0;
	int NumberOfLevels = 0;

	int Level;
	if ( firststatus == 0 )
	{
		Level = 0;
	}
	else if ( firststatus == 1 )
	{
		Level = 1;
	}

	if ( type != W_CONST )
	{
		int NumberOfChanges = changes.GetCount();
		if ( NumberOfChanges < 2 || changes[0] >= 0 )
		{
			return;
		}

		int CycleMultiplier = (int)-changes[0];
		int ChangesInCycle = 0;
		CArray<char,char> NumberOfChangesIsOddInCycle;
		for ( int i = 1; i < NumberOfChanges; i++ )
		{
			if ( changes[i] < 0 )
			{
				NumberOfChangesIsOddInCycle.Add( char(ChangesInCycle % 2) );
				CycleMultiplier = (int)-changes[i];
				ChangesInCycle = 0;
				continue;
			}
			NumberOfLevels+= CycleMultiplier;
			ChangesInCycle++;
		}
		NumberOfChangesIsOddInCycle.Add( char(ChangesInCycle % 2) );

		NumberOfLevels++;

		bool MultipleRepetition = false;
		int CyclesCounter = -1;
		__int64 TotalTimeCounter=0;
		for ( int i = 0; i < NumberOfChanges; i++ )
		{
			if ( changes[i] >= 0 )
			{
				TotalTimeCounter += CycleMultiplier*changes[i];
				if ( TotalTimeCounter > TotalTime )
				{
					StatusList->AddMessage( "WARNING: Signal <"+this->name+"> is out of range. All statistics values may be incorrect." );
					break;
				}
				if ( MultipleRepetition == false || NumberOfChangesIsOddInCycle[CyclesCounter] == false )
				{
					if ( changes[i] > Maximum[Level] )
					{
						Maximum[Level] = changes[i];
					}
					if ( changes[i] < Minimum[Level] )
					{
						Minimum[Level] = changes[i];
					}
					SumForMean[Level] += changes[i] * CycleMultiplier;
					Level = (Level+1)%2;
				}
				else
				{
					for ( int j = 0; j < 2; j++ )
					{
						if ( changes[i] > Maximum[j] )
						{
							Maximum[j] = changes[i];
						}
						if ( changes[i] < Minimum[j] )
						{
							Minimum[j] = changes[i];
						}
					}
					SumForMean[Level] += changes[i] * ((CycleMultiplier+1)/2);
					SumForMean[(Level+1)%2] += changes[i] * (CycleMultiplier/2);
					Level = (Level + (CycleMultiplier % 2) ) % 2;
				}
			}
			else
			{
				if ( changes[i] < -1 )
				{
					MultipleRepetition = true;
				}
				else
				{
					MultipleRepetition = false;
				}
				CycleMultiplier = (int)-changes[i];
				CyclesCounter++;
			}
		}
		if ( TotalTime > TotalTimeCounter )
		{
			if ( TotalTime - TotalTimeCounter > Maximum[Level] )
			{
				Maximum[Level] = TotalTime - TotalTimeCounter;
			}
			if ( TotalTime - TotalTimeCounter < Minimum[Level] )
			{
				Minimum[Level] = TotalTime - TotalTimeCounter;
			}
			SumForMean[Level] += TotalTime - TotalTimeCounter;
		}
	}
	else
	{
		Minimum[(Level+1)%2] = 0;
		Maximum[ Level ] = TotalTime;
		SumForMean[ Level ] = TotalTime;
		NumberOfLevels = 1;
	}
	for ( int i = 0 ; i < 2; i++ )
	{
		SignalStatistics.MaxTimeInLevel[i] = Maximum[i];
		SignalStatistics.MinTimeInLevel[i] = Minimum[i];
		SignalStatistics.SumOfTimesInLevel[i] = SumForMean [i];
	}
	SignalStatistics.NumberOfLevels[firststatus] = (NumberOfLevels+1)/2;
	SignalStatistics.NumberOfLevels[(firststatus+1)%2] = NumberOfLevels/2;

	return;
}

WaveSignalStatistics SimpleWavesignal::GetSignalStatistics()
{
	return SignalStatistics;
}

//////////////////////////////////////////////////////////////////////
// group Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

group::group(mymessages	*_StatusList)
{
	name				=	"No name";
	StatusList			=	_StatusList;
	group_is_defined	=	FALSE;
}



group::~group()
{

}



CString group::GetName()
{
	return name;
}



void group::SetName(CString _name)
{
	name	=	_name;
	name.Replace(" ",NULL);
}



void group::SetComment(CString _comment)
{
	comments	=	_comment;
}



CString group::GetComments()
{
	return comments;
}


void group::SetFileName(CString _filename)
{
	filename	=	_filename;
}



CString group::GetFileName()
{
	return filename;
}


void group::DefineGroup()
{
	group_is_defined	=	TRUE;
}


void group::UnDefineGroup()
{
	group_is_defined	=	FALSE;
}


BOOL group::GetGroupStatus()
{
	return group_is_defined;
}





BYTE group::GetType()
{
	return type;
}


void group::SetType(BYTE  NewType)
{
	type	=	NewType;
}


CString group::GetStatusLine()
{
	return "<"+name+">"+" ( "+comments+"  )";
}






unsigned long group::GetStartPositionInScriptFile()
{
	return startpositioninscriptfile;
}

unsigned long group::GetEndPositionInScriptFile()
{
	return endpositioninscriptfile;
}

void group::SetStartPositionInScriptFile(unsigned long num)
{
	startpositioninscriptfile	=	num;
}

void group::SetEndPositionInScriptFile(unsigned long num)
{
	endpositioninscriptfile		=	num;
}



unsigned long group::GetStartPositionInVectorFile()
{
	return startpositioninvectorfile;
}

unsigned long group::GetEndPositionInVectorFile()
{
	return endpositioninvectorfile;
}

void group::SetStartPositionInVectorFile(unsigned long num)
{
	startpositioninvectorfile	=	num;
}

void group::SetEndPositionInVectorFile(unsigned long num)
{
	endpositioninvectorfile		=	num;
}


//////////////////////////////////////////////////////////////////////
// complex_group Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

complex_group::complex_group(mymessages	*_StatusList):group(_StatusList)
{
	StatusList			=	_StatusList;
	ClearAllComponent();
		
}

void complex_group::ClearAllComponent()
{
	numberofcomponents	=	0;
	for(int i = 0;i<MAXIMUM_INGROUP;i++)
	{
		groups[i]	=	"";
	}
}

complex_group::~complex_group()
{

}

int complex_group::AddComponent(CString _group, WORD _sequences)
{
	for(int i = 0;i<MAXIMUM_INGROUP;i++)
	{
		if(groups[i]	==	"")
		{
			groups[i]						=	_group;
			numberofsequencespercomponent[i]=	_sequences;
			numberofcomponents++;
			return 0;
		}
	}
	CString	res	=	"ERROR:Cannot add new group ";
	res			+=	_group;
	res			+=	"	to complex_group";
	res			+=	name;
	StatusList->AddMessage(res);
	return -1;	
}

int complex_group::GetNumberOfComponents()
{
	return numberofcomponents;
}

CString complex_group::GetComponentName(int pos)
{
	if(pos <numberofcomponents)
	{
		return groups[pos];
	}
	return "";
}

int complex_group::GetComponentSequences(int pos)
{
	if(pos <numberofcomponents)
	{
		return numberofsequencespercomponent[pos];
	}
	return -1;
}

CString complex_group::GetComponentStatusLine(int pos)
{
	char	num[10];
	_itoa(numberofsequencespercomponent[pos],num,10);
	CString _result	=	" * ";
	_result			+=	num;
	return _result;
}



//////////////////////////////////////////////////////////////////////
// simple_group Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

simple_group::simple_group( mymessages *_StatusList, ScenarioSignals* gsignals ) : group( _StatusList )
, numberoffilevectors(0), CutOffSpace(0)
{
	globalsignals	=	gsignals;
	StatusList		=	_StatusList;
	NumberOfSignals = globalsignals->GetNumberOfSignals();
    wavesignals = new wavesignal*[NumberOfSignals];
    memset(&wavesignals[0], 0, sizeof(wavesignal*) * NumberOfSignals);
}

void simple_group::ReallocateWaveSignals()
{
	wavesignal **OldWaveSignals = wavesignals;
	int NewNumberOfSignals = globalsignals->GetNumberOfSignals();
	wavesignals = new wavesignal*[ NewNumberOfSignals ];
	memset( wavesignals, 0, sizeof(wavesignal*) * NewNumberOfSignals );
	for (int i = 0; i < NumberOfSignals; i++)
	{
		if ( AddSignal( OldWaveSignals[i] ) == false )
		{
			delete OldWaveSignals[i];
		}
	}
	NumberOfSignals = NewNumberOfSignals;
	delete[] OldWaveSignals;
}

simple_group::~simple_group()
{
	for(int i=0;i<NumberOfSignals;i++)
	{
		if(wavesignals[i]	!= NULL)
		{
			delete wavesignals[i];
		}
	}
    delete[] wavesignals;
}

void simple_group::SetClockPeriod( unsigned __int64 _clk )
{
	clocks	=	_clk;
}


bool simple_group::AddSignal(wavesignal* _signal)
{
	if ( _signal == NULL )
	{
		return false;
	}
	CString signname	=	_signal->GetName();
	int		pos		=	globalsignals->GetSignalNumber(signname);
	if(pos <0)
	{
		return false;
	}
	if ( _signal->type != W_GROUP )
	{
		((SimpleWavesignal*)_signal)->SetNumberInFile(globalsignals->GetNumberOfSignals()-pos);
	}
	if ( wavesignals[pos] != 0 )
	{
		StatusList->AddMessage( "WARNING: Signal \"" + signname + "\" attends more than one time in the same group. The first copy is lost" );
		delete wavesignals[pos];
	}
	wavesignals[pos]	=	_signal;	
	globalsignals->SetSignalUsed(pos);
	return true;
}

void simple_group::FillArrayOfWaveSignalsByNamesOfIncludedSignals( CArray<SimpleWavesignal*, SimpleWavesignal*> *Signals, int NumberOfSignal)
{
	if ( NumberOfSignal < 0 )
	{
		return;
	}
	int NumberOfIncludedSignals = globalsignals->GetSignalsInGroup(NumberOfSignal)->GetCount();
	for( int i = 0; i < NumberOfIncludedSignals; i++ )
	{
		Signals->Add( (SimpleWavesignal*)wavesignals[ (*globalsignals->GetSignalsInGroup(NumberOfSignal))[i] ] );
	}
}

wavesignal* simple_group::GetPointerToWavesignalByIndex(int Index)
{
	return ((Index >= 0) && ( Index < globalsignals->GetNumberOfSignals() )) ? wavesignals[Index] : NULL;
}

int simple_group::CheckForVectorFile(CString line)
{
	CString			command;
	char			vline[MAXIMUMLINELENGTH];
	int pos[2];
	int p[3];
	
	if(line.Find("file",0) <0)
	{
		return -1;
	}
	pos[0]	=	line.Find('"',0);
	pos[1]	=	line.Find('"',pos[0]+1);
	if((pos[0]	<	0)||(pos[1]	<	0))
	{
		CString	res	=	"ERROR:Wrong FILE definition in GROUP ";
		res			+=	name;
		StatusList->AddMessage(res);
		return -1;
	}
//-------------------------------------------------------------------------------------------------
	CString		param[4];
	CString		pparam[4];
//------------------------------------------------------
	int			numofparam	=	3;
	pparam[0]	=	""	;param[0]	=	"htotal";
	pparam[1]	=	""	;param[1]	=	"vtotal";
	pparam[2]	=	""	;param[2]	=	"ee";
//	pparam[3]	=	subres	;param[3]	=	"subres";
//------------------------------------------------------
	int i=0;
	for(;i<numofparam;i++)
	{
		p[0]			=	line.Find(param[i],0);
		if(p[0] >0)
		{
			p[1]			=	line.Find('=',p[0]);
			p[2]			=	line.Find(' ',p[1]);
			if(p[2]<0)
			{
				pparam[i]		=	line.Mid(p[1]+1);
			}
			else
			{
				if((p[2]-p[1]) == 1)
				{
					p[1]			=	p[2];
					p[2]			=	line.Find(' ',p[1]);
				}
				if(p[2]<0)
				{
					pparam[i]		=	line.Mid(p[1]+1);
				}
				else
				{
					pparam[i]		=	line.Mid(p[1]+1,p[2]-p[1]-1);
				}
			}
		}
	}
//-------------------------------------------------------------------------------------------------
	for(i=0;i<numofparam;i++)
	{
		if(pparam[i]	==	"")
		{
			CString res	= "Vector File Error :: Please define "+param[i]+" argument";
			return -1;
		}
	}
	CString file_name	=	line.Mid(pos[0]+1,pos[1]-pos[0]-1);
	FILE	*vfile;
	if((vfile	=	fopen(file_name,"r")) == NULL)
	{
		CString	res	=	"ERROR:Cannot open FILE  definition in GROUP";
		res			+=	name;
		StatusList->AddMessage(res);
		return -1;
	}
	
	fgets(vline,MAXIMUMLINELENGTH,vfile);
	command	=	vline;
	command.TrimLeft("\t ");
	command.Replace("\t"," ");
	command.MakeLower();
	command.Remove('\n');
	if(ReadSignalsNameFromFile(command) !=	0)
	{
		fclose(vfile);
		return -1;
	}
	fclose(vfile);
	CString optimizedfilename	=	OptimizeVectorFile(file_name,param,pparam,numofparam);
	if(optimizedfilename == "-1")
	{
		return -1;
	}

	if((vfile	=	fopen(optimizedfilename,"r")) == NULL)
	{
		CString	res	=	"ERROR:File <"+optimizedfilename+"> is corrupted (there is may be wrong definition for file ";
		res			+=	"<"+file_name+">";
		StatusList->AddMessage(res);
		return -1;
	}
	while(fgets(vline,MAXIMUMLINELENGTH,vfile) >0)
	{
		CString		_line	=	vline;
		if(_line.Find("Line") <0)
		{
			DistributeBitsToSignals(_line);
		}
	}
	fclose(vfile);
	FinilizeReadingSignals();
	return 0;
}

void simple_group::RefreshWavesignalsGroups()
{
	for( int i = 0; i < this->NumberOfSignals; i++ )
	{
		if ( wavesignals[i]->type == W_GROUP )
		{
			delete wavesignals[i];
			GroupOfWavesignals* NewGroup = new GroupOfWavesignals( StatusList );
			wavesignals[i] = NewGroup;
			NewGroup->FillDataOfWavesignalGroup( globalsignals->GetSignalName( i ), i, this );
		}
	}
}

int simple_group::ReadSignalsNameFromFile(CString line)
{
	int pos[2];
	CString templine	=	line;
	int numberofnames	=	0;
	int namenumber		=	0;
	numberoffilevectors	=	-1;
	if(templine[0]	==	' ')
	{
		templine	=	templine.Mid(1);
	}
	while(templine.GetLength()>0)
	{
		pos[0]	=	templine.Find(' ',0);
		if(pos[0]	< 0)
		{
			pos[0]	=	templine.GetLength();
		}
		CString tempname	=	templine.Mid(0,pos[0]);
		pos[1]	=	globalsignals->GetSignalNumber(tempname);
		if(pos[1]	>=0)
		{
			numberofnames++;
			SimpleWavesignal*	newsignal	=	new SimpleWavesignal(StatusList);
			newsignal->SetNumberInFile	(namenumber);
			newsignal->SetName			(tempname);
			newsignal->SetSignalType	(W_PWM_FILE);
			newsignal->SetFirstValues	();
			globalsignals->SetSignalUsed(pos[1]);
			AddSignal(newsignal);
		}
		templine	=	templine.Mid(pos[0]+1);
		namenumber++;
	}
	if(numberofnames	==	0)
	{
		return -1;
	}
	numberoffilevectors	=	namenumber-1;
	return	0;
}

DWORD simple_group::GetAbsoluteOffset(CString time)
{
	CString szTIME	="";
	CString szUS	="";
	for(int i=0;i<time.GetLength();i++)
	{
		if((time[i]==',')||(time[i]=='.')||((time[i] >='0')&&(time[i]<='9')))
		{
			continue;
		}
		else
		{
			szTIME	=	time.Mid(0,i-1);
			szUS	=	time.Mid(i);
			i		=	time.GetLength();
		}
	}
	return DWORD(mfrom_file.ParseTime((char*)LPCTSTR(szTIME),(char*)LPCTSTR(szUS))/0.04);
}


int simple_group::DistributeBitsToSignals(CString _line)
{
	if(numberoffilevectors	<1)
	{
		return -1;
	}
	_line.Remove(' ');_line.Remove('\t');_line.Remove('\n');
	int startn	=_line.Find("(");
	int	endn	=_line.Find(".");
	if((startn	<	0)||(endn	<0))
	{
		return -1;
	}
	DWORD absoluteoffset	=	_atoi64(_line.Mid(startn+1,endn-startn));
	for(int i=0;i<NumberOfSignals;i++)
	{
		if((wavesignals[i] != NULL)&&(wavesignals[i]->GetSignalType() == W_PWM_FILE))
		{
			((SimpleWavesignal*)wavesignals[i])->AddBit(_line[((SimpleWavesignal*)wavesignals[i])->GetNumberInFile()-1]-'0',absoluteoffset);
		}

	}
	return 0;
}

int simple_group::FinilizeReadingSignals(void)
{
	for(int i=0;i<NumberOfSignals;i++)
	{
		if((wavesignals[i] != NULL)&&(wavesignals[i]->GetSignalType() == W_PWM_FILE))
		{
			wavesignals[i]->SetSignalType(W_PWM);
		}

	}
	return 0;
}



BYTE simple_group::ConvertCharToBit(char _bit)
{
	if(_bit	==	'0')
	{
		return 0;
	}
	if(_bit	==	'1')
	{
		return 1;
	}
	return -1;
}




int simple_group::PutBitInSignal(int signalpos, BYTE _bit, __int64 absoluteoffset)
{
	for(int	i=0;i<NumberOfSignals;i++)
	{
		if((wavesignals[i] != NULL)&&(wavesignals[i]->GetSignalType() == W_PWM_FILE)&&(((SimpleWavesignal*)wavesignals[i])->GetNumberInFile() == signalpos))
		{
			((SimpleWavesignal*)wavesignals[i])->AddBit(_bit,absoluteoffset);
			return	0;
		}
	}
	return -1;
}



void simple_group::ExportInformation()
{
	StatusList->AddMessage("The script file is ("+filename+")");
	StatusList->AddMessage("The group <"+name+"> is a basic group");
	StatusList->AddMessage("The basic group name is <"+comments+">  Clock period  "+GetStrClock());
	StatusList->AddMessage("signal list:");
	for(int i=0;i<NumberOfSignals;i++)
	{
		if(wavesignals[i]	!= NULL )
		{
			if ( wavesignals[i]->type != W_GROUP )
			{
				((SimpleWavesignal*)wavesignals[i])->ExportInfo();
			}
		}
	}
}



CString simple_group::GetStrClock()
{
	char number[20];
	_i64toa(clocks,number,10);
	return number;
}

__int64 simple_group::GetClock()
{
	return clocks;
}

__int64 simple_group::WriteComponentToVectorFile(FILE *pVfile, unsigned __int64 startposition)
{
	SetSignalsReadFirstValue();
	
	for(DWORD i=0;i<clocks-1;i++)
	{
		char bits_line[150];
		int curpos=0;
		for( DWORD ii = 0; ii < NumberOfSignals;ii++)
		{
			if(globalsignals->CheckIfSignalWasUsed(ii) == TRUE)
			{
				if(wavesignals[ii] == NULL && wavesignals[ii]->type != W_GROUP )
				{
					bits_line[curpos]	= '0';
				}
				else
				{
					bits_line[curpos]	=((SimpleWavesignal*)wavesignals[ii])->GetBitName();
				}
				curpos++;
			}
		}
		bits_line[curpos] = '\0';

		writeline++;
		if(bits_line != old_vector)
		{
			old_vector		=	bits_line;
			__int64 cicle	=	startposition + i;
			char number[10];
			_i64toa(cicle,number,10);
			strcat(bits_line,"  ");
			strcat(bits_line,number);
			strcat(bits_line,"\n");
			myfputs(bits_line,pVfile);
		}
	}
	return startposition +clocks;
}

__int64 simple_group::WriteComponentToGraphData(graphdata		*graph, 
											  unsigned __int64 startposition,
											  unsigned __int64 offset,
											  unsigned __int64 delta,
											  int TimeDivider)
{
	if ( startposition/TimeDivider > offset + delta || (startposition + clocks)/TimeDivider < offset )
	{
		return startposition + clocks;
	}
	for(int i=0;i<NumberOfSignals;i++)
	{
		if(wavesignals[i] == NULL)
		{
			if ( globalsignals->GetType(i) != GROUP_OF_SIGNALS )
			{
				wavesignals[i]	=	new SimpleWavesignal(StatusList);
			}
			else
			{
				wavesignals[i]	=	new GroupOfWavesignals(StatusList);
			}
			wavesignals[i]->SetName( globalsignals->GetSignalName( i ));
		}
		HighlightingRule NewRule = globalsignals->GetRule(i);
		NewRule.Min /= TimeDivider;
		NewRule.Max /= TimeDivider;
		wavesignals[i]->WriteComponentToGraphData(graph,startposition,offset, delta, (clocks-1), TimeDivider, i, NewRule );
	}
	return startposition + clocks;
}

/*	previous version
DWORD simple_group::WriteComponentToGraphData(graphdata *graph, unsigned long startposition,unsigned long offset)
{
	SetSignalsReadFirstValue();
	int NumberOfSignals	=	globalsignals->GetNumberOfSignals();
	for(DWORD i=0;i<clocks-1;i++)
	{
		graph->newsignal();
		DWORD pos	=	0;
		for(DWORD ii=0;ii<NumberOfSignals;ii++)
		{
			BYTE bit;
//			if(globalsignals->CheckIfSignalWasUsed(ii) == TRUE)
//			{
				if(wavesignals[ii] == NULL)
				{
					bit	=	0;
				}
				else
				{
					bit	=	wavesignals[ii]->GetBit();
				}
				
				graph->PutBitInSignal(bit,pos);
				pos++;
//			}
		}
//-------------------------- write to graph data with zoom ratio rule-------------------------------------		
		DWORD	pagelen	=	graph->GetPageLength();
		DWORD	zoomrat	=	graph->GetZoomRatio();
		if( ( (startposition+i)%(zoomrat) )	==	0)	
		{															
			if(((startposition + i) >= offset)&&( ((startposition + i)-offset) < pagelen))
			{
				graph->AddSignal();								
			}
		}															
		else														
		{															
			graph->CompareWithLastSignal();							
		}															
//--------------------------------------------------------------------------------------------------------
	}
	return startposition + clocks;
}
*/

void simple_group::SetSignalsReadFirstValue()
{
	for( int i=0;i<NumberOfSignals;i++)
	{
		if(wavesignals[i] != NULL && wavesignals[i]->type != W_GROUP )
		{
			((SimpleWavesignal*)wavesignals[i])->SetFirstValues();
		}
	}
}

CString simple_group::OptimizeVectorFile(CString filename, CString* paramname, CString* paramarg, int numofparam)
{
	ZWaveeditorApp	*pWinapp=	(ZWaveeditorApp*) AfxGetApp();
	CString			root   =	'"'+pWinapp->ConfigurationDirectory+"\\utg_compressor.exe"+'"';;
	CString outputfilename	=	filename+".opt";
	for(int i=0;i<numofparam;i++)
	{
		root	+=	" -"+paramname[i];
		root	+=	" "	+paramarg[i];
	}
	CString additional		=	" -input "+filename+" -stat";
	additional				+=	" -vectors "+outputfilename;
	root					+=	additional;
	system(root);
//	FILE *batFile ;
//	batFile	=	fopen("C:\\DIMA\\command.bat","w");
//	if(batFile	!=	NULL)
//	{
//			fwrite(LPCTSTR(root),root.GetLength(),1,batFile);
//			fclose(batFile);
//	}

	return outputfilename;
}

WaveSignalStatistics simple_group::GetSignalStatistics( int SignalNumber )
{
	wavesignal *CS = wavesignals[SignalNumber];
	if ( wavesignals[SignalNumber]->type != W_GROUP )
	{
		return ((SimpleWavesignal*)wavesignals[SignalNumber])->GetSignalStatistics();
	}
	else
	{
		WaveSignalStatistics SignalStatistics;
		return SignalStatistics;
	}
}

void simple_group::ReturnFreeSpace()
{
	for ( int i = 0; i < NumberOfSignals; i++ )
	{
		try
		{
			wavesignals[i]->SetFirstTimingChange( wavesignals[i]->GetFirstTimingChangeAfterTime( 0 ) + CutOffSpace );
		}
		catch ( WrongTypeOfWavesignal )
		{
		}
	}
	clocks += CutOffSpace;
	CutOffSpace = 0;
}

void simple_group::CutFreeSpace()
{
	unsigned __int64 MinimalChange = -1;
	unsigned __int64 TemporaryChange;
	for ( int i = 0; i < NumberOfSignals; i++ )
	{
		try
		{
			TemporaryChange = wavesignals[i]->GetFirstTimingChangeAfterTime( 0 );
			if ( MinimalChange > TemporaryChange )
			{
				MinimalChange = TemporaryChange;
			}
		}
		catch ( WrongTypeOfWavesignal )
		{
		}
	}
	CutOffSpace += ( MinimalChange != -1)?MinimalChange - 1 : 0;
	clocks -= CutOffSpace;
	for ( int i = 0; i < NumberOfSignals; i++ )
	{
		try
		{
			wavesignals[i]->SetFirstTimingChange( wavesignals[i]->GetFirstTimingChangeAfterTime( 0 ) - CutOffSpace );
		}
		catch ( WrongTypeOfWavesignal )
		{
		}
	}
}

//////////////////////////////////////////////////////////////////////
// frame Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

frame::frame(mymessages	*_StatusList):group(_StatusList)
{
	StatusList			=	_StatusList;
	ClearAllComponents();
}

void frame::ClearAllComponents()
{
	for(int i = 0;i<MAXIMUM_INGROUP;i++)
	{
		groups[i]	=	"";
	}
	numberofcomponents	=	0;
}

frame::~frame()
{

}

int frame::AddComponent(CString _group, WORD _sequences)
{
	for(int i = 0;i<MAXIMUM_INGROUP;i++)
	{
		if(*groups[i]	==	NULL)
		{
			groups[i]						=	_group;
			numberofsequencespercomponent[i]=	_sequences;
			numberofcomponents++;
			return 0;
		}
	}
	CString	res	=	"ERROR:Cannot add new group ";
	res			+=	_group;
	res			+=	"	to FRAME";
	res			+=	name;
	StatusList->AddMessage(res);
	return -1;	

}


int frame::GetNumberOfComponents()
{
	return numberofcomponents;
}

CString frame::GetComponentName(int pos)
{
	if(pos <numberofcomponents)
	{
		return groups[pos];
	}
	return "";
}

int frame::GetComponentSequences(int pos)
{
	if(pos <numberofcomponents)
	{
		return numberofsequencespercomponent[pos];
	}
	return -1;
}

CString frame::GetComponentStatusLine(int pos)
{
	char	num[10];
	_itoa(numberofsequencespercomponent[pos],num,10);
	CString _result	=	" * ";
	_result			+=	num;
	return _result;
}


CString frame::GetHTotal()
{
	return htotal;
}

CString frame::GetVTotal()
{
	return vtotal;
}

CString frame::GetCompressor()
{
	return compressor;
}

CString frame::GetVTotal_2()
{
	
	int number	=	atoi(vtotal);
	if(number >2)
	{
		char	num[10];
		number	-=	2;
		itoa(number,num,10);
		return num;
	}
	return vtotal;
}

CString frame::GetNFS()
{
	return nfs;
}
CString frame::GetSubRes()
{
	return subres;
}

void frame::SetHTotal(CString num)
{
	htotal	=	num;
}

void frame::SetCompressor(CString ver)
{
	compressor	=	ver;
}

void frame::SetVTotal(CString num)
{
	vtotal	=	num;
}

void frame::SetNFS(CString num)
{
	nfs	=	num;
}
void frame::SetSubRes(CString num)
{
	subres	=	num;
}

//////////////////////////////////////////////////////////////////////
// scenario Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

scenario::scenario(mymessages	*_StatusList, CString FileName )
{
	for(int i=0;i<MAXIMUM_GROUPS;i++)
	{
		groups[i]	=	NULL;
	}
	name			=	"Default";
	globalsignals	=	new ScenarioSignals( _StatusList );	
	scenariodefined	=	FALSE;
	numberofgroups	=	0;
	StatusList		=	_StatusList;
	filename		=	FileName;
	wsdialogexist	=	FALSE;
	TimeDivider		=	1;
	FreeSpaceCutOff = true;
	LogReadType.TypeOfBracketLines = LogReadType.TypeOfNoBracketLines = BY_WORD;
}




scenario::~scenario()
{
	DeleteAll();
}



void scenario::SetName(CString paramname)
{
	name	=	paramname;	
}

bool scenario::CreateSimpleGroupForScriptFromLog( const CArray< Signal, Signal > &Signals, unsigned __int64 TotalSize )
{
	bool Result = false;
	selectedgroup	=	GetNumberOfGroupByName( DEFAULT_GROUP_NAME,W_SIMPLE,FALSE);
	if(selectedgroup >= 0 && groups[selectedgroup]->GetGroupStatus() == FALSE )
	{
		groups[selectedgroup]->SetComment("\"" + DEFAULT_GROUP_COMMENT + "\"");
		groups[selectedgroup]->SetFileName(filename);
		simple_group* Group	=	(simple_group*)groups[selectedgroup];
		Group->SetClockPeriod( TotalSize );
		for ( unsigned int i = 0; i < Signals.GetSize(); i++ )
		{
			if( Signals[i].Changes.GetSize() >= 1)
			{
				SimpleWavesignal*	newwavesignal	=	new SimpleWavesignal(StatusList, Signals[i] );
				newwavesignal->ComputeSignalStatistics( Group->GetClock() );
				if ( Group->AddSignal(newwavesignal) == false )
				{
					delete newwavesignal;
				}
			}
		}
		Group->DefineGroup();
		Result = true;
	}
	else
	{
		StatusList->AddMessage("ERROR: Can't create new group: \"" + DEFAULT_GROUP_NAME + "\"");
	}
	
	return Result;
}

bool scenario::CreateFrameForScriptFromLog( unsigned __int64 TotalSize )
{
	bool Result = false;
	selectedgroup	=	GetNumberOfGroupByName( DEFAULT_FRAME_NAME, W_FRAME, FALSE );
	if ( selectedgroup >= 0 && groups[selectedgroup]->GetGroupStatus() == FALSE )
	{
		HTotal = Long64ToCString(TotalSize);
		VTotal = "1";
		SubRes = Compressor = NFS = "";
		
		groups[selectedgroup]->SetComment( "\"" + DEFAULT_GROUP_COMMENT + "\"" );
		groups[selectedgroup]->SetFileName(filename);

		frame* pframe	=	(frame*) groups[selectedgroup];
		pframe->SetHTotal	(HTotal);
		pframe->SetVTotal	(VTotal);
		pframe->SetNFS		(NFS);
		pframe->SetSubRes	(SubRes);
		pframe->SetCompressor(Compressor);
		pframe->AddComponent( DEFAULT_GROUP_NAME, 1 );
		pframe->DefineGroup();
		Result = true;
	}
	else
	{
		StatusList->AddMessage( "ERROR: Can't create frame: \"" + DEFAULT_FRAME_NAME + "\"" );
	}
	return Result;
}

bool scenario::LoadSignalsFromArray( const CArray< Signal, Signal > &Signals, unsigned __int64 TotalSize )
{
	bool Result = false;
	if(globalsignals->SignalsExist()	==	TRUE )
	{
		OriginalTimeType = ( Signals[0].TimeType == MILLI_SECONDS ) ? "ms" : "us";

		if ( CreateSimpleGroupForScriptFromLog( Signals, TotalSize ) == true &&
			CreateFrameForScriptFromLog( TotalSize ) == true )
		{
			scenariodefined	=	TRUE;
			CheckScriptDefinitions();
			Result = true;
		}
	}
	else
	{
		StatusList->AddMessage("ERROR:Signals list not defined .Please load signals list ");
	}
	return Result;
}


long scenario::LoadScriptFile( CString file_name )
{
	long Result = -1;
	CString			command;
	BOOL     scriptFileOpenResult = scriptfile.Open(file_name, CFile::modeRead | CFile::typeText);
	if ( scriptFileOpenResult == TRUE )
	{
		if ( globalsignals->SignalsExist() == TRUE )
		{
			linenumber	=	0;

			while ( scriptfile.ReadString(line) )
			{	
				linenumber++;
				command	=	rebuild_string_to_command(line);
				CheckIfGroupBegin(command);
			}
			
			scriptfile.Close();
			scenariodefined	=	TRUE;
			CheckScriptDefinitions();
			Result = 0;
		}
		else
		{
			StatusList->AddMessage( "ERROR:Signals list not defined .Please load signals list " );
		}
	}
	else
	{
		StatusList->AddMessage( "ERROR:Cannnot open script file :"+file_name );
	}
	return Result;
}

int scenario::GetNumberOfGroupByName(CString _name,BYTE Type,BOOL rewriting)
{
	int position	=	0;
	_name.Replace(" ",NULL);
	while(groups[position] != NULL)
	{
		if((groups[position]->GetName() == _name)&&(groups[position]->GetFileName()	==	filename))
		{
			if(rewriting == TRUE)
			{
				delete groups[position];
				groups[position]	=	NULL;
				numberofgroups--;
				continue;
			}
			else
			{
				return position;
			}
		}
		position ++;
	}
	
	
	if(Type == 0)
	{
		return -1;
	}
	
	if(position <MAXIMUM_GROUPS)
	{
		switch(Type)
		{
			case W_COMPLEX:
							{
								groups[position]	=(complex_group*)	new complex_group(StatusList);
								groups[position]->SetType(W_COMPLEX);
								numberofgroups++;
							};break;
			case W_SIMPLE:
							{
								groups[position]	=(simple_group*)	new simple_group(StatusList,globalsignals);
								groups[position]->SetType(W_SIMPLE);
								numberofgroups++;
							};break;
			case W_FRAME:
							{
								groups[position]	=(frame*)			new frame(StatusList);
								groups[position]->SetType(W_FRAME);
								numberofgroups++;
							};break;
			case W_DEFAULT:
							{
								groups[position]	=(simple_group*)	new simple_group(StatusList,globalsignals);
								groups[position]->SetType(W_DEFAULT);
								numberofgroups++;
							};break;

		}
		groups[position]->SetName(_name);
		groups[position]->SetFileName(filename);
		groups[position]->UnDefineGroup();
		return position;
	}
	
	CString	res	=	"ERROR:Cannot add new group :";
	res			+=	_name;
	res			+=	"in	line:";
	res			+=	GetLineNumber();
	StatusList->AddMessage(res);
	
	return -1;
}




int scenario::SubProccessInLoadingScriptFile(CString _line,CString groupcomment,int number,BYTE Type)
{
	CString command;
	if(groups[selectedgroup]->GetGroupStatus() == TRUE)
	{
		return -1;
	}

	groups[selectedgroup]->SetComment(groupcomment);
	groups[selectedgroup]->SetFileName(filename);
	groups[selectedgroup]->SetStartPositionInScriptFile(linenumber);
	switch(Type)
	{
		case W_COMPLEX:
						{
							while(scriptfile.ReadString(line))
							{
								linenumber++;
								command	=	rebuild_string_to_command(line);
								if(command.Find("complex_group_end",0) > -1)
								{
									groups[selectedgroup]->DefineGroup();
									groups[selectedgroup]->SetEndPositionInScriptFile(linenumber);
									return 0;
								}
								int oldselect	=	selectedgroup;
								if(CheckIfGroupBegin(command) == 0)
								{
									selectedgroup	=	oldselect;
									continue;
								}
								StringToGroupsSequences LineInFrameOrComplexGroup;
								if(LineInFrameOrComplexGroup.LoadExpression(command)	==	0)
								{
									complex_group* _complex	=	(complex_group*)groups[selectedgroup];
									for(int i=0;i<LineInFrameOrComplexGroup.numberofgroups;i++)
									{
										_complex->AddComponent(LineInFrameOrComplexGroup.groups[i],LineInFrameOrComplexGroup.numberofsequnces[i]);
										GetNumberOfGroupByName(LineInFrameOrComplexGroup.groups[i],W_DEFAULT,FALSE);
									}
								}

							}
							return 0;
						};break;
		case W_FRAME:
						{
							if((HTotal == "")||(VTotal == ""))
							{
								char num[10];
								_itoa(linenumber,num,10);
								CString snum	=	num;
								StatusList->AddMessage("WARNING:You didn't define vtotal or htotal [line number : "+snum+"] script "+groups[selectedgroup]->GetFileName()+" frame : "+groups[selectedgroup]->GetName());
							}
							frame* pframe	=	(frame*) groups[selectedgroup];
							pframe->SetHTotal	(HTotal);
							pframe->SetVTotal	(VTotal);
							pframe->SetNFS		(NFS);
							pframe->SetSubRes	(SubRes);
							pframe->SetCompressor(Compressor);

							while(scriptfile.ReadString(line))
							{
								linenumber++;
								command	=	rebuild_string_to_command(line);
								if(command.Find("frame_end",0) > -1)
								{
									groups[selectedgroup]->DefineGroup();
									groups[selectedgroup]->SetEndPositionInScriptFile(linenumber);
									return 0;
								}
								int oldselect	=	selectedgroup;
								if(CheckIfGroupBegin(command) == 0)
								{
									selectedgroup	=	oldselect;
									continue;
								}
								StringToGroupsSequences LineInFrameOrComplexGroup;
								if(LineInFrameOrComplexGroup.LoadExpression(command)	==	0)
								{
									frame* _frame	=	(frame*)groups[selectedgroup];
									for(int i=0;i<LineInFrameOrComplexGroup.numberofgroups;i++)
									{
										_frame->AddComponent(LineInFrameOrComplexGroup.groups[i],LineInFrameOrComplexGroup.numberofsequnces[i]);
										GetNumberOfGroupByName(LineInFrameOrComplexGroup.groups[i],W_DEFAULT,FALSE);
									}
								}

							}
							return 0;
						};break;
		case W_SIMPLE:
						{
							simple_group* _group	=	(simple_group*)groups[selectedgroup];
							_group->SetClockPeriod(number);

							while(scriptfile.ReadString(line))
							{
								linenumber++;
								command	=	rebuild_string_to_command(line);
								if(command.Find("group_end",0) > -1)
								{
									groups[selectedgroup]->DefineGroup();
									groups[selectedgroup]->SetEndPositionInScriptFile(linenumber);
									return 0;
								}
								SimpleWavesignal*	newwavesignal	=	new SimpleWavesignal(StatusList);
								int res	=	newwavesignal->uploadstring( command, line );
								if(res	==	0)
								{
									newwavesignal->ComputeSignalStatistics( _group->GetClock() );
									if ( _group->AddSignal(newwavesignal) == false )
									{
										delete newwavesignal;
									}
								}
								else
								{
									delete newwavesignal;
									_group->CheckForVectorFile(command);
								}
								
							}
							return 0;
						};break;
	}
	CString	res	=	"WARNING:unknown definition :";
	res			+=	"in	line:";
	res			+=	GetLineNumber();
	StatusList->AddMessage(res);
	return -1;
}




void scenario::GetGroupFormatFromLine(CString scriptline,CString *groupname,CString *comment,int *number, CString *TimeType )
{
	int p[6];
	p[0]	=	scriptline.Find(' ',0);
	if(p[0]<1)
	{
		p[0]=	scriptline.Find(' ',p[0]+1);
	}
	p[1]			=	scriptline.Find(' ',p[0]+1);
	p[2]			=	scriptline.Find('"',p[0]+1);
	if(p[2]<p[1])
	{
		p[1]	=	p[2];
	}
	*groupname		=	scriptline.Mid(p[0]+1,p[1]-p[0]-1);
	if(scriptline.GetLength() <= (p[1]+1))
	{
		*comment	= "";	
		*number		= -1;
		return;
	}
	p[2]			=	scriptline.Find('"',0);
	p[3]			=	scriptline.Find('"',p[2]+1);
	*comment		=	scriptline.Mid(p[2]+1,p[3]-p[2]-1);
	if(scriptline.GetLength() <= (p[3]+1))
	{
		*number		= -1;
		return;
	}
	p[4]			=	scriptline.Find(' ',p[3]);
	p[5]			=	scriptline.Find(' ',p[4]+1);
	if(p[4] <0)
	{
		p[4]=p[3]+1;
	}
	if(p[5] < 0 )
	{
		CString	num 	=	scriptline.Mid( p[4]+1, scriptline.GetLength() - p[4] - 1 );
		*number			=	atol(num);
		*TimeType = "ms";
		return;
	}
	CString	num 	=	scriptline.Mid(p[4]+1,p[5] - p[4] - 1);
	*number			=	atol(num);
	*TimeType		=	scriptline.Mid(p[5]+1, scriptline.GetLength() - p[5] - 1);
}



void scenario::GetFrameFormatFromLine(CString scriptline, CString *groupname, CString *comment, CString *htotal, CString *vtotal,CString *nfs,CString *subres,CString *compressor)
{
	*htotal		=	"";
	*vtotal		=	"";
	*nfs		=	"";
	*subres		=	"";
	*compressor	=	"";
	myFormatString frmtstr;
	CString sep	="\t\n =";
	CString s1 ='"';
	frmtstr.FormatString(scriptline,sep);
	int i=0;
	for(;i<frmtstr.numofparts;i++)
	{
		if(frmtstr.parts[i].Find("frame")>=0)
		{
			*groupname	=	frmtstr.parts[i+1];
			if(frmtstr.parts[i+2].Find(s1) >=0)
			{
				*comment	=	frmtstr.parts[i+2];
			}
			i			=	frmtstr.numofparts;
		}
	}
	CString		param[5];
	CString		*pparam[5];
	pparam[0]	=	htotal		;param[0]	=	"htot";
	pparam[1]	=	vtotal		;param[1]	=	"vtot";
	pparam[2]	=	nfs			;param[2]	=	"nfs";
	pparam[3]	=	subres		;param[3]	=	"subres";
	pparam[4]	=	compressor	;param[4]	=	"comp";
	for(i=0;i<5;i++)
	{
		for(int ii=0;ii<frmtstr.numofparts;ii++)
		{
			if(frmtstr.parts[ii].Find(param[i]) >=0)
			{
				*pparam[i]	=	frmtstr.parts[ii+1];
				ii	=	frmtstr.numofparts;
			}
		}
	}
}


/* old version
void scenario::GetFrameFormatFromLine(CString scriptline, CString *groupname, CString *comment, CString *htotal, CString *vtotal,CString *nfs,CString *subres,CString *compressor)
{
	*htotal		=	"";
	*vtotal		=	"";
	*nfs		=	"";
	*subres		=	"";
	*compressor	=	"";
	
	int p[5];
	//--------------------------  read frame name --------------------------------------
	p[0]	=	scriptline.Find(' ',0);
	if(p[0]<1)
	{
		p[0]=	scriptline.Find(' ',p[0]+1);
	}
	p[1]			=	scriptline.Find(' ',p[0]+1);
	p[2]			=	scriptline.Find('"',p[0]+1);
	if(p[2]<p[1])
	{
		p[1]	=	p[2];
	}
	*groupname		=	scriptline.Mid(p[0]+1,p[1]-p[0]-1);
//--------------------------  read frame comment name --------------------------------
	if(scriptline.GetLength() <= (p[1]+1))
	{
		*comment	= "";	
		return;
	}
	p[2]			=	scriptline.Find('"',0);
	p[3]			=	scriptline.Find('"',p[2]+1);
	*comment		=	scriptline.Mid(p[2]+1,p[3]-p[2]-1);
	if(scriptline.GetLength() <= (p[3]+1))
	{
		return;
	}
//--------------------------  read frame format  --------------------------------------
	CString		param[5];
	CString		*pparam[5];
	pparam[0]	=	htotal	;param[0]	=	"htot";
	pparam[1]	=	vtotal	;param[1]	=	"vtot";
	pparam[2]	=	nfs		;param[2]	=	"nfs";
	pparam[3]	=	subres	;param[3]	=	"subres";
	pparam[4]	=	compressor	;param[4]	=	"comp";
	for(int i=0;i<5;i++)
	{
		p[0]			=	scriptline.Find(param[i],0);
		if(p[0] >0)
		{
			p[1]			=	scriptline.Find('=',p[0]);
			p[2]			=	scriptline.Find(' ',p[1]);
			if(p[2]<0)
			{
				*pparam[i]		=	scriptline.Mid(p[1]+1);
			}
			else
			{
				if((p[2]-p[1]) == 1)
				{
					p[1]			=	p[2];
					p[2]			=	scriptline.Find(' ',p[1]);
				}
				if(p[2]<0)
				{
					*pparam[i]		=	scriptline.Mid(p[1]+1);
				}
				else
				{
					*pparam[i]		=	scriptline.Mid(p[1]+1,p[2]-p[1]-1);
				}
			}
		}
	}
}
*/
CString scenario::rebuild_string_to_command(CString _line)
{
	int pos = _line.Find("//",0);
	if(pos>-1)
	{
		_line	=	_line.Mid(0,pos);
	}
	_line.MakeLower();
	_line.Replace('\t',' ');
	_line.TrimLeft();//" ");
	for(int i=1;i<_line.GetLength();i++)
	{
		if(((_line[i-1] == ' ')||(_line[i-1] == '\t'))&&((_line[i] == ' ')||(_line[i] == '\t')))
		{
			_line.SetAt(i,'\t');
		}
	}

	_line.Remove('\t');
	_line.Remove('\n');
	_line.Remove('\r');
	return _line;
}

__int64 scenario::GetDistanceAndCommentBetweenNearestChanges( CPoint point, CString& Comment )
{
	int SignalNumber = globalsignals->GetSignalNumber( point );	
	simple_group* Group = (simple_group*)groups[0];
	SimpleWavesignal* pCurrentSignal = (SimpleWavesignal*)Group->GetPointerToWavesignalByIndex( SignalNumber ) ;
    __int64 TrueCoord = mygraphdata.GetTrueCoordinates( point.x ) * TimeDivider;
	__int64 MaxTime   = Group->GetClock();
	__int64 Interval = ( NULL != pCurrentSignal ) ? pCurrentSignal->GetInterval( TrueCoord, MaxTime, &Comment ) : -1;
	if ( Interval != -1 )
		Interval /= TimeDivider;
	return Interval;
}


int scenario::CheckIfGroupBegin(CString _line)
{
	int					stringposition;
 	CString				groupname;
	CString				groupcomment;
	int					number	=	0;//number of sequences in group modul
	CString				TimeType;
//      This part of code works with complex group
	if((stringposition	=	_line.Find("end",0)) > -1)
	{
		StatusList->AddMessage("ERROR:Error in script - unexpected end of group/frame  - line number :"+GetLineNumber());
		return -1;
	}
	if((stringposition	=	_line.Find("complex_group",0)) > -1)
	{
		GetGroupFormatFromLine(_line,&groupname,&groupcomment,&number, &TimeType);
		selectedgroup	=	GetNumberOfGroupByName(groupname,W_COMPLEX,FALSE);

		if(selectedgroup < 0)
		{
			StatusList->AddMessage("ERROR:Error in script - can't create new complex_group  - line number :"+GetLineNumber());
			return -1;
		}
//
//		here code for checking double setting for one complex group 
//
		if(groups[selectedgroup]->GetGroupStatus() == TRUE)
		{
			StatusList->AddMessage("ERROR:Error in script - double definition for one complex_group  - line number : "+GetLineNumber());
			return -1;
		}
		SubProccessInLoadingScriptFile(_line,groupcomment,number,W_COMPLEX);
		return 0;
	}

	
//      This part of code works with simple group
	if((stringposition	=	_line.Find("group",0)) > -1)
	{
		GetGroupFormatFromLine(_line,&groupname,&groupcomment,&number, &TimeType);
		OriginalTimeType = TimeType;
		selectedgroup	=	GetNumberOfGroupByName(groupname,W_SIMPLE,FALSE);

		if(selectedgroup < 0)
		{
			StatusList->AddMessage("ERROR:Error in script - can't create new group  - line number :"+GetLineNumber());
			return -1;
		}
//
//		here code for checking double setting for one group 
//
		if(groups[selectedgroup]->GetGroupStatus() == TRUE)
		{
			StatusList->AddMessage("ERROR:Error in script - double definition for one group  - line number : "+GetLineNumber());
			return -1;
		}
		SubProccessInLoadingScriptFile(_line,groupcomment,number,W_SIMPLE);
		return 0;
	}

	
//      This part of code works with frame
	if((stringposition	=	_line.Find("frame",0)) > -1)
	{
		GetFrameFormatFromLine(_line,&groupname,&groupcomment,&HTotal,&VTotal,&NFS,&SubRes,&Compressor);
		selectedgroup	=	GetNumberOfGroupByName(groupname,W_FRAME,FALSE);

		if(selectedgroup < 0)
		{
			StatusList->AddMessage("ERROR:Error in script - can't create frame  - line number :"+GetLineNumber());
			return -1;
		}
//
//		here code for checking double setting for one group 
//
		if(groups[selectedgroup]->GetGroupStatus() == TRUE)
		{
			StatusList->AddMessage("ERROR:Error in script - double definition for one frame -  line number : "+GetLineNumber());
			return -1;
		}
		SubProccessInLoadingScriptFile(_line,groupcomment,number,W_FRAME);
		return 0;
	}
	return -1;
}

long scenario::UpDateAllFromFile()
{
	DeleteAll();
	LoadGlobalSignalListFromScriptFile( filename );
	return LoadScriptFile(filename);
}

void scenario::DeleteAll()
{
	for(int i=0;i<MAXIMUM_GROUPS;i++)
	{
		if(groups[i] != NULL)
		{
			delete groups[i];
			groups[i] = NULL;
		}
	}
	scenariodefined	=	FALSE;
	numberofgroups	=	0;
	delete globalsignals;
	globalsignals = NULL;
	scenariotree.RemoveAll();
}




int scenario::LoadGlobalSignalList(ScenarioSignals	*_signals)
{
	globalsignals	=	_signals;
	return 0;
}

void scenario::LoadGlobalSignalListFromScriptFile(CString FileName)
{
	delete globalsignals;
	globalsignals = new ScenarioSignals( StatusList );
	globalsignals->LoadSignalsFromScriptFile( FileName );
	globalsignals->SetDefaults();
}

void scenario::LoadGlobalSignalListFromArray( const CArray< Signal, Signal > &Signals )
{
	delete globalsignals;
	globalsignals = new ScenarioSignals( StatusList );
	globalsignals->LoadSignalsFromArray( Signals );
}

CString scenario::GetFileName()
{
	return filename;
}

BOOL scenario::GetScenarioStatus()
{
	return scenariodefined;
}

int scenario::ExportTree(CTreeCtrl *_tree,DWORD treenum)
{
	int pos	=	filename.Find('.',0);
	if(pos<0)
	{
		pos	=	filename.GetLength();
	}
	CString		rootname=	filename.Mid(0,pos);	
	LastTreeNumber	=	treenum;
	TreeNumber			=	LastTreeNumber^10;
	HTREEITEM	root	=	InsertItem(_tree,rootname,NULL,0,0);
	scenariotree.RemoveAll();
	scenariotree.Add(root);
	for( int i=0; i < numberofgroups; i++)
	{
		if( groups[i]->GetType() == W_FRAME )
		{
			HTREEITEM	_parent	=	InsertItem(_tree,groups[i]->GetStatusLine(),root,1,1);
			scenariotree.Add(_parent);;
			AddFrameORGroupToTree(_tree,_parent,groups[i]);
		}
	}
	return 0;
}

int scenario::AddFrameORGroupToTree(CTreeCtrl *_item, HTREEITEM _parent,group* parentgroup)
{
	HTREEITEM	tpos;
	switch(parentgroup->GetType())
	{
		case W_FRAME:
					{
						frame *tgroup = (frame*) parentgroup;
						for(int i=0;i<tgroup->GetNumberOfComponents();i++)
						{
							group		*compgroup	=	groups[GetNumberOfGroupByName(tgroup->GetComponentName(i),W_DEFAULT,FALSE)];
							CString		status		=	compgroup->GetStatusLine();
							status					+=	tgroup->GetComponentStatusLine(i);
							BYTE		_Type		=	compgroup->GetType();
							switch(_Type)
							{
								case W_FRAME:
										{
											tpos		=	InsertItem(_item,status,_parent,1,1);
										};break;
								case W_COMPLEX:
										{
											tpos		=	InsertItem(_item,status,_parent,2,2);
										};break;
								default:
										{
											tpos		=	InsertItem(_item,status,_parent,3,3);
										};break;
							}
							scenariotree.Add(tpos);
							if((_Type	==	W_FRAME)||(_Type	==	W_COMPLEX))
							{
								AddFrameORGroupToTree(_item,tpos,compgroup);
							}
						}
						
					}break;
		case W_COMPLEX:
					{
						complex_group *tgroup = (complex_group*) parentgroup;
						for(int i=0;i<tgroup->GetNumberOfComponents();i++)
						{
							group		*compgroup	=	groups[GetNumberOfGroupByName(tgroup->GetComponentName(i),W_DEFAULT,FALSE)];
							CString		status		=	compgroup->GetStatusLine();
							status					+=	tgroup->GetComponentStatusLine(i);
							BYTE		_Type		=	compgroup->GetType();
							switch(_Type)
							{
								case W_FRAME:
										{
											tpos		=	InsertItem(_item,status,_parent,1,1);
										};break;
								case W_COMPLEX:
										{
											tpos		=	InsertItem(_item,status,_parent,2,2);
										};break;
								default:
										{
											tpos		=	InsertItem(_item,status,_parent,3,3);
										};break;
							}
							scenariotree.Add(tpos);
							if((_Type	==	W_FRAME)||(_Type	==	W_COMPLEX))
							{
								AddFrameORGroupToTree(_item,tpos,compgroup);
							}
						}
						
					};break;
	}
	return 0;
}


CString scenario::GetLineNumber()
{
	char	num[10];
	_itoa(linenumber,num,10);
	CString res	=	num;
	return res;
}


BOOL scenario::CheckIfSelectedTree(HTREEITEM pos)
{
	for(int i=0;i<scenariotree.GetSize();i++)
	{
		if(scenariotree[i]	==	pos)
		{
			return TRUE;
		}
	}
	return FALSE;
}

inline int scenario::GetSignalFromGraphView( CPoint point )
{
	int GroupNumber = globalsignals->GetSignalNumber( point );
	int SignalNumberInGroup = globalsignals->GetSignalNumberInGroupFromGraphView( point.y );

	if (( GroupNumber >= 0 ) && ( SignalNumberInGroup > -1 ))
	{
		int SignalNumber = globalsignals->GetSignalsInGroup( GroupNumber )->GetAt( SignalNumberInGroup );
		USHORT PositionInGraph = (WORD)(point.x/mygraphdata.GetDeltax());
		byte SignalBit = mygraphdata.GetBitInSignal( PositionInGraph, SignalNumber ) % 10;

		if ( globalsignals->CheckIfHighOrLowLevelOfSignal( point.y ) == SignalBit )	
			return globalsignals->GetSignalsInGroup( GroupNumber )->GetAt(SignalNumberInGroup);
	}
	return GroupNumber;
}

CString scenario::GetSignalNameInGroupFromGraphView( CPoint point )
{
	int Index = GetSignalFromGraphView( point );
	return ( Index >= 0 ) ? globalsignals->GetSignalName( Index ) : "";
}

BOOL scenario::CheckIfSelectedScriptRoot(HTREEITEM pos)
{
	for(int i=0;i<scenariotree.GetSize();i++)
	{
		if(scenariotree[i]	==	pos)
		{
			if(i	==	0)
			{
				return TRUE;
			}
			else
			{
				StatusList->AddMessage("ERROR:You must select root definition for this action");
				StatusList->AddMessage("ERROR:Please select <"+filename+">");
				return FALSE;
			}
		}
	}
	return FALSE;

}

BOOL scenario::CheckIfSelectedFrame(CTreeCtrl *_tree,HTREEITEM pos)
{
	for(int i=0;i<scenariotree.GetSize();i++)
	{
		if(scenariotree[i]	==	pos)
		{
			CString name				=	_tree->GetItemText(pos);
			int posbegin				=	name.Find("<",0);
			int posend					=	name.Find(">",0);
			name						=	name.Mid(posbegin+1,posend-posbegin-1);
			int selected				=	GetNumberOfGroupByName(name,0,FALSE);
			if(selected == -1)
			{
				return FALSE;
			}
			if(groups[selected]->GetType()	!=	W_FRAME)
			{
				return FALSE;
			}
			else
			{
				return TRUE;
			}
		}
	}
	return FALSE;

}

BOOL scenario::CheckIfSelectedGroup(CTreeCtrl *_tree,HTREEITEM pos)
{
	for(int i=0;i<scenariotree.GetSize();i++)
	{
		if(scenariotree[i]	==	pos)
		{
			CString name				=	_tree->GetItemText(pos);
			int posbegin				=	name.Find("<",0);
			if(posbegin	< 0)
			{
				return FALSE;
			}
			int posend					=	name.Find(">",0);
			if(posend	< 0)
			{
				return FALSE;
			}
			name						=	name.Mid(posbegin+1,posend-posbegin-1);
			int selected				=	GetNumberOfGroupByName(name,0,FALSE);
			if(selected == -1)
			{
				return FALSE;
			}
			return TRUE;
		}
	}
	return FALSE;

}

CString scenario::GetFileNameOnly()
{
	CString name;
	int pos	=	filename.ReverseFind('\\');
	name	=	filename.Mid(pos+1);
	return name;
}

CString scenario::GetNameOnly(void)
{
	CString name;
	int pos	=	filename.ReverseFind('\\');
	name	=	filename.Mid(pos+1);
	pos		=	name.Find(".");
	if(pos>=0)
	{
		name	=	name.Mid(0,pos);
	}
	return name;
}


int scenario::GenerateVectorFileFromFrame(CString framename,FILE *pVfile)
{
	int selected		=	GetNumberOfGroupByName(framename,W_DEFAULT,FALSE);
	if(groups[selected]->GetType()	!=	W_FRAME)
	{
		StatusList->AddMessage("ERROR:Selected Item  <"+framename+"> is not frame");
		StatusList->AddMessage("ERROR:Please select frame item to generate vector file");
		return -1;
	}
	globalsignals->WriteToVectorFile(pVfile);
	frame		*selectedframe		=	(frame*)groups[selected];
	if(GetNumberOffClocksInGroup(selectedframe) == -1)
	{
		return -1;
	}
	
	if(wsdialogexist	==	TRUE)
	{
		writeline					=	0;
		wsdialog->SetFrame			(selectedframe->GetName());
		wsdialog->SetFrameName		(selectedframe->GetComments());
		wsdialog->SetNumberOfLines	(numberofclocksingroup);
		wsdialog->SetScriptName		(filename);
		wsdialog->SetLineNumber		(writeline);
	}
	old_vector	="";
	WriteComponentToVectorFile	(pVfile,groups[selected],0);
	return 0;		
}

int scenario::SetGraphDataTotalSize( graphdata *GraphData, CString GroupName )
{
	int selected = GetNumberOfGroupByName(GroupName,W_DEFAULT,FALSE);
	if( groups[selected]->GetGroupStatus()	==	FALSE )
	{
		StatusList->AddMessage("ERROR:Selected Item  <"+groups[selected]->GetName()+"> is not defined");
		return -1;
	}
	unsigned long graphlengthres	=	GetNumberOffClocksInGroup(groups[selected]);
	if( graphlengthres	== -1)
	{
		StatusList->AddMessage("ERROR:Cannot show graph : error in group database");
		return -1;
	}
	__int64 TotalSize = numberofclocksingroup/TimeDivider;
	if ( TotalSize == -1 )
	{
		return -1;
	}
	GraphData->SetTotalSize( TotalSize );
	return 0;
}

int scenario::FirstInitGraphData( graphdata *GraphData, CString GroupName, unsigned __int64 offset,unsigned __int64 delta, long WindowMaxX )
{
	int selected = GetNumberOfGroupByName(GroupName,W_DEFAULT,FALSE);
	if( InitGraphData( GraphData, selected, offset, delta, WindowMaxX ) >= 0)
	{
		GraphData->AddSignalsName( globalsignals );
		GraphData->SetGroupName(GroupName);
		GraphData->_1stmark.x_true = GraphData->_1stmark.x_relative = GraphData->globaloffset;
		GraphData->_1stmark.optimize = FALSE;
		GraphData->_1stmark.signalID = -1;
		GraphData->_2ndmark.x_true = GraphData->_2ndmark.x_relative = GraphData->globaloffset + GraphData->globaldelta;
		GraphData->_2ndmark.optimize = FALSE;
		GraphData->_2ndmark.signalID = -1;
		selectedgroup = selected;
		return 0;
	}
	return -1;
}

int scenario::InitGraphData( graphdata *GraphData, CString groupname, unsigned __int64 offset,unsigned __int64 delta,int windowmaxx)
{
	int selected		=	GetNumberOfGroupByName(groupname,W_DEFAULT,FALSE);
	return InitGraphData( GraphData, selected, offset, delta, windowmaxx);
}

int scenario::InitGraphData( graphdata *GraphData, int selected, unsigned __int64 offset,unsigned __int64 delta,int windowmaxx)
{
	if( groups[selected]->GetGroupStatus()	==	FALSE )
	{
		StatusList->AddMessage("ERROR:Selected Item  <"+groups[selected]->GetName()+"> is not defined");
		return -1;
	}
	GraphData->RemoveAll();
	DWORD	windowratio	=	2;
	if (GraphData->InitGraphData( delta,offset,windowmaxx,windowratio, globalsignals->GetNumberOfSignals(), GetCurrentTimeType() ) )
    {
        StatusList->AddMessage("ERROR:Cannot show graph : insufficient memory");
        return -1;
    }
	WriteComponentToGraphData(groups[selected],0,offset, delta,0, GraphData);
	GraphData->FinilizeSignalInGraph( globalsignals, GetPositionOfFirstGroupAfterGlobalPosition ( groups[selected], offset+delta, 0 ) );
	GraphData->AddSignalsName( globalsignals );
	return 0;
}




int scenario::OnItemInfo(CString item_name)
{
	CString _name			=	item_name;
	int		selectedgroup	=	GetNumberOfGroupByName(_name,0,FALSE);
	if(selectedgroup == -1)
	{
		return -1;
	}
	if(groups[selectedgroup]->GetGroupStatus()	==	FALSE)
	{
		StatusList->AddMessage("ERROR:Selected Item  <"+_name+"> is not defined");
		StatusList->AddMessage("ERROR:Please define this group and update :"+filename+" script");
		return -1;
	} 
	switch(groups[selectedgroup]->GetType())
	{
		case W_FRAME:
					{
						frame* pframe	=	(frame*) groups[selectedgroup];
						StatusList->AddMessage("The script file is ("+filename+")");
						StatusList->AddMessage("The group <"+item_name+"> is a frame");
						StatusList->AddMessage("The frame name is <"+pframe->GetComments()+">");
						StatusList->AddMessage("htotal	: "+pframe->GetHTotal());
						StatusList->AddMessage("vtotal	: "+pframe->GetVTotal());
						StatusList->AddMessage("NFS		: "+pframe->GetNFS());
						StatusList->AddMessage("SubRes	: "+pframe->GetSubRes());
						
					};break;
		case W_COMPLEX:
					{
						StatusList->AddMessage("The script file is ("+filename+")");
						StatusList->AddMessage("The group <"+item_name+"> is a complex group");
						StatusList->AddMessage("The complex group name is <"+groups[selectedgroup]->GetComments()+">");
					};break;
		case W_SIMPLE:
					{
						simple_group*	grp	=	(simple_group*) groups[selectedgroup];
						grp->ExportInformation();
					};break;
	}
	return 0;
}











unsigned __int64 scenario::WriteComponentToVectorFile(FILE *pVfile,group *wgroup,unsigned __int64 startposition)
{
	switch(wgroup->GetType())
	{
		case W_FRAME:
					{
						frame *selectedframe	=	(frame*) wgroup;
						for(int i=0;i<selectedframe->GetNumberOfComponents();i++)
						{
							CString compname	=	selectedframe->GetComponentName(i);
							int		compseq		=	selectedframe->GetComponentSequences(i);
							int		pos			=	GetNumberOfGroupByName(compname,W_DEFAULT,FALSE);
							for(int ii=0;ii<compseq;ii++)
							{
								startposition	=	WriteComponentToVectorFile(pVfile,groups[pos],startposition);
							}
						}
					};break;
		case W_COMPLEX:
					{
						complex_group *selectedcomplex	=	(complex_group*) wgroup;
						for(int i=0;i<selectedcomplex->GetNumberOfComponents();i++)
						{
							CString compname	=	selectedcomplex->GetComponentName(i);
							int		compseq		=	selectedcomplex->GetComponentSequences(i);
							int		pos			=	GetNumberOfGroupByName(compname,W_DEFAULT,FALSE);
							for(int ii=0;ii<compseq;ii++)
							{
								startposition	=	WriteComponentToVectorFile(pVfile,groups[pos],startposition);
							}
						}
					};break;
		case W_SIMPLE:
					{
						simple_group*	grp	=	(simple_group*) wgroup;
						startposition		=	grp->WriteComponentToVectorFile(pVfile,startposition);					
					};break;
	}
	return startposition;
}





unsigned __int64 scenario::WriteComponentToGraphData(group *wgroup, unsigned __int64 startposition,unsigned __int64 offset, unsigned __int64 delta,WORD deepness, graphdata *GraphData)
{
	switch(wgroup->GetType())
	{
		case W_FRAME:
					{
						frame *selectedframe	=	(frame*) wgroup;
						for(int i=0;i<selectedframe->GetNumberOfComponents();i++)
						{
							CString compname	=	selectedframe->GetComponentName(i);
							int		compseq		=	selectedframe->GetComponentSequences(i);
							int		pos			=	GetNumberOfGroupByName(compname,W_DEFAULT,FALSE);
							for(int ii=0;ii<compseq;ii++)
							{
								startposition	=	WriteComponentToGraphData(groups[pos],startposition,offset, delta,deepness+1, GraphData);
							}
						}
					};break;
		case W_COMPLEX:
					{
						complex_group *selectedcomplex	=	(complex_group*) wgroup;
						for(int i=0;i<selectedcomplex->GetNumberOfComponents();i++)
						{
							CString compname	=	selectedcomplex->GetComponentName(i);
							int		compseq		=	selectedcomplex->GetComponentSequences(i);
							int		pos			=	GetNumberOfGroupByName(compname,W_DEFAULT,FALSE);
							for(int ii=0;ii<compseq;ii++)
							{
								startposition	=	WriteComponentToGraphData(groups[pos],startposition,offset, delta, deepness+1, GraphData);
							}
						}
					};break;
		case W_SIMPLE:
					{
						simple_group*	grp	=	(simple_group*) wgroup;
						startposition		=	grp->WriteComponentToGraphData(GraphData,startposition,offset,delta, TimeDivider);					
					};break;
	}
	return startposition;

}

WaveSignalStatistics scenario::GetStatisticsOfWavesignalInShownGroup( int SignalNumber )
{
	WaveSignalStatistics bestWaveSignalStatistics = GetStatisticsOfWavesignal( groups[selectedgroup], SignalNumber );
	bestWaveSignalStatistics.ConvertToMS( TimeDivider );
	return bestWaveSignalStatistics;
}

WaveSignalStatistics scenario::GetStatisticsOfWavesignal(group *wgroup, int SignalNumber)
{
	WaveSignalStatistics SignalStatistics;
	WaveSignalStatistics bestWaveSignalStatistics;

	switch(wgroup->GetType())
	{
		case W_FRAME:
					{
						frame *selectedframe	=	(frame*) wgroup;
						for(int i=0;i<selectedframe->GetNumberOfComponents();i++)
						{
							CString compname	=	selectedframe->GetComponentName(i);
							int		compseq		=	selectedframe->GetComponentSequences(i);
							int		pos			=	GetNumberOfGroupByName(compname,W_DEFAULT,FALSE);
							for(int ii=0;ii<compseq;ii++)
							{
								SignalStatistics = GetStatisticsOfWavesignal( groups[pos], SignalNumber );
								bestWaveSignalStatistics.UpdateWaveSignalStatistics( SignalStatistics );
							}
						}
					};break;
		case W_COMPLEX:
					{
						complex_group *selectedcomplex	=	(complex_group*) wgroup;
						for(int i=0;i<selectedcomplex->GetNumberOfComponents();i++)
						{
							CString compname	=	selectedcomplex->GetComponentName(i);
							int		compseq		=	selectedcomplex->GetComponentSequences(i);
							int		pos			=	GetNumberOfGroupByName(compname,W_DEFAULT,FALSE);
							for(int ii=0;ii<compseq;ii++)
							{
								SignalStatistics = GetStatisticsOfWavesignal( groups[pos], SignalNumber );
								bestWaveSignalStatistics.UpdateWaveSignalStatistics( SignalStatistics );
							}
						}
					};break;
		case W_SIMPLE:
					{
						simple_group*	grp	=	(simple_group*) wgroup;
						SignalStatistics = grp->GetSignalStatistics( SignalNumber );
						bestWaveSignalStatistics.UpdateWaveSignalStatistics( SignalStatistics );
					};break;
	}
	return bestWaveSignalStatistics;

}




int scenario::CheckScriptDefinitions()
{
	for(int i=0;i<numberofgroups;i++)
	{
		CString name	=	groups[i]->GetName();
		if((groups[i] != NULL)&& (groups[i]->GetGroupStatus() == FALSE))
		{
			StatusList->AddMessage("WARNING: The group   <"+groups[i]->GetName()+">  is not defined");
		}
	}
	return 0;
}


int scenario::OnEditscriptfile(CString name, mymessages *templist)
{
	CString _name		=	name;
	int		selected	=	GetNumberOfGroupByName(_name,0,FALSE);
	if(selected == -1)
	{
		return -1;
	}
	if(groups[selected]->GetGroupStatus()	==	FALSE)
	{
		StatusList->AddMessage("ERROR:Selected Item  <"+_name+"> is not defined");
		StatusList->AddMessage("ERROR:Please define this group and update :"+filename+" script");
		return -1;
	} 
	templist->ClearLog();

	CStdioFile pFile;
	BOOL scriptFileOpenResult = pFile.Open(filename, CFile::modeRead | CFile::typeText);

	if(scriptFileOpenResult == FALSE)
	{
		StatusList->AddMessage("ERROR:Cannot open script file  <"+filename+">");
		return -1;
	}
	int startposition		=	groups[selected]->GetStartPositionInScriptFile();
	int endposition			=	groups[selected]->GetEndPositionInScriptFile();
	
	offsetinfile			=	startposition;
	startblockfileposition	=	startposition;
	endblockfileposition	=	endposition;
	int fileposition		=	0;

	while(pFile.ReadString(line))
	{
		//Initialization of insensitive string without spacebars and tabulators		
		fileposition++;
		if((fileposition >= startposition)&&(fileposition <= endposition))
		{
			CString _line	=	line;
			int pos			=	_line.Find("\n",0);
			if(pos >= 0)
			{
				_line.Insert(pos,"\r\r");
			}
			else
			{
				_line.Append("\r\n");
			}
			templist->AddMessage(_line);
		}
	}

	pFile.Close();
	return 0;
}



void scenario::UpDateScriptFromTempList(mymessages	*_templist)
{
	templist	=	_templist;
	CString			command;
	linenumber	=	0;
	while(linenumber < (unsigned long)templist->GetNumberOfMessages())
	{
		//Initialization of insensitive string without spacebars and tabulators		
		command	=	templist->GetMessage(linenumber);
		command	=	rebuild_string_to_command(command);
		CheckIfGroupBegin2(command);
		linenumber++;
	}
	
	scenariodefined	=	TRUE;
	CheckScriptDefinitions();
	return ;

}


int scenario::SubProccessInEditingScriptFile(CString _line, CString groupcomment, int number, BYTE Type)
{
	CString command;
//	if(groups[selectedgroup]->GetGroupStatus() == TRUE)
//	{
//		return -1;
//	}

	groups[selectedgroup]->SetComment(groupcomment);
	groups[selectedgroup]->SetFileName(filename);
	groups[selectedgroup]->SetStartPositionInScriptFile(linenumber+offsetinfile);
	switch(Type)
	{
		case W_COMPLEX:
						{
							while(linenumber < (unsigned long)templist->GetNumberOfMessages())
							{
								linenumber++;
								command	=	templist->GetMessage(linenumber);
								command	=	rebuild_string_to_command(command);
								if(command.Find("complex_group_end",0) > -1)
								{
									groups[selectedgroup]->DefineGroup();
									groups[selectedgroup]->SetEndPositionInScriptFile(linenumber+offsetinfile);
									return 0;
								}
								int oldselect	=	selectedgroup;
								if(CheckIfGroupBegin2(command) == 0)
								{
									selectedgroup	=	oldselect;
									continue;
								}
								StringToGroupsSequences LineInFrameOrComplexGroup;
								if(LineInFrameOrComplexGroup.LoadExpression(command)	==	0)
								{
									complex_group* _complex	=	(complex_group*)groups[selectedgroup];
									_complex->ClearAllComponent();
									for(int i=0;i<LineInFrameOrComplexGroup.numberofgroups;i++)
									{
										_complex->AddComponent(LineInFrameOrComplexGroup.groups[i],LineInFrameOrComplexGroup.numberofsequnces[i]);
										GetNumberOfGroupByName(LineInFrameOrComplexGroup.groups[i],W_DEFAULT,FALSE);
									}
								}

							}
							return 0;
						};break;
		case W_FRAME:
						{
							if((HTotal == "")||(VTotal == ""))
							{
								char num[10];
								_itoa(linenumber,num,10);
								CString snum	=	num;
								StatusList->AddMessage("WARNING:You didn't define vtotal or htotal [line number : "+snum+"] script "+groups[selectedgroup]->GetFileName()+" frame : "+groups[selectedgroup]->GetName());
								
							}
							frame* pframe	=	(frame*) groups[selectedgroup];
							pframe->SetHTotal	(HTotal);
							pframe->SetVTotal	(VTotal);
							pframe->SetNFS		(NFS);
							pframe->SetSubRes	(SubRes);
							pframe->SetCompressor(Compressor);

							while(linenumber < (unsigned long)templist->GetNumberOfMessages())
							{
								linenumber++;
								command	=	templist->GetMessage(linenumber);
								command	=	rebuild_string_to_command(command);
								if(command.Find("frame_end",0) > -1)
								{
									groups[selectedgroup]->DefineGroup();
									groups[selectedgroup]->SetEndPositionInScriptFile(linenumber+offsetinfile);
									return 0;
								}
								int oldselect	=	selectedgroup;
								if(CheckIfGroupBegin2(command) == 0)
								{
									selectedgroup	=	oldselect;
									continue;
								}
								StringToGroupsSequences LineInFrameOrComplexGroup;
								if(LineInFrameOrComplexGroup.LoadExpression(command)	==	0)
								{
									frame* _frame	=	(frame*)groups[selectedgroup];
									_frame->ClearAllComponents();
									for(int i=0;i<LineInFrameOrComplexGroup.numberofgroups;i++)
									{
										_frame->AddComponent(LineInFrameOrComplexGroup.groups[i],LineInFrameOrComplexGroup.numberofsequnces[i]);
										GetNumberOfGroupByName(LineInFrameOrComplexGroup.groups[i],W_DEFAULT,FALSE);
									}
								}

							}
							return 0;
						};break;
		case W_SIMPLE:
						{
							simple_group* _group	=	(simple_group*)groups[selectedgroup];
							_group->SetClockPeriod(number);
							while(linenumber < (unsigned long)templist->GetNumberOfMessages())
							{
								linenumber++;
								command	=	templist->GetMessage(linenumber);
								CString OldCommand = command;
								command	=	rebuild_string_to_command(command);
								if(command.Find("group_end",0) > -1)
								{
									groups[selectedgroup]->DefineGroup();
									groups[selectedgroup]->SetEndPositionInScriptFile(linenumber+offsetinfile);
									return 0;
								}
								SimpleWavesignal*	newwavesignal	=	new SimpleWavesignal(StatusList);
								int res	=	newwavesignal->uploadstring(command, OldCommand);
								if(res	==	0)
								{
									_group->AddSignal(newwavesignal);	
								}
								else
								{
									delete newwavesignal;
									_group->CheckForVectorFile(command);
								}
								
							}
							return 0;
						};break;
	}
	CString	res	=	"ERROR:Unknown definition :";
	res			+=	"in	line:";
	res			+=	GetLineNumber();
	StatusList->AddMessage(res);
	return -1;

}

int scenario::CheckIfGroupBegin2(CString _line)
{
	int					stringposition;
	CString				groupname;
	CString				groupcomment;
	int					number		=	0;//number of sequences in group modul
	CString				TimeType;
//      This part of code works with complex group
	if((stringposition	=	_line.Find("complex_group",0)) > -1)
	{
		GetGroupFormatFromLine(_line,&groupname,&groupcomment,&number, &TimeType);
		selectedgroup	=	GetNumberOfGroupByName(groupname,W_COMPLEX,TRUE);

		if(selectedgroup < 0)
		{
			StatusList->AddMessage("ERROR:Error in script - can't create new complex_group  - line number :"+GetLineNumber());
			return -1;
		}
		SubProccessInEditingScriptFile(_line,groupcomment,number,W_COMPLEX);
		return 0;
	}

	
//      This part of code works with simple group
	if((stringposition	=	_line.Find("group",0)) > -1)
	{
		GetGroupFormatFromLine(_line,&groupname,&groupcomment,&number, &TimeType);
		selectedgroup	=	GetNumberOfGroupByName(groupname,W_SIMPLE,TRUE);

		if(selectedgroup < 0)
		{
			StatusList->AddMessage("ERROR:Error in script - can't create new group  - line number :"+GetLineNumber());
			return -1;
		}
		SubProccessInEditingScriptFile(_line,groupcomment,number,W_SIMPLE);
		return 0;
	}

	
//      This part of code works with frame
	if((stringposition	=	_line.Find("frame",0)) > -1)
	{
		GetFrameFormatFromLine(_line,&groupname,&groupcomment,&HTotal,&VTotal,&NFS,&SubRes,&Compressor);
		selectedgroup	=	GetNumberOfGroupByName(groupname,W_FRAME,TRUE);

		if(selectedgroup < 0)
		{
			StatusList->AddMessage("ERROR:Error in script - can't create frame  - line number :"+GetLineNumber());
			return -1;
		}
		SubProccessInEditingScriptFile(_line,groupcomment,number,W_FRAME);
		return 0;
	}
	return -1;

}



void scenario::UpDateScriptFileFromTempList(mymessages *_templist)
{
	templist				=	_templist;
	CString		tempfile	=	filename+".temp";
	FILE		*fdest,*fsrc;
	if	((CopyFile(filename,tempfile,FALSE)		==	FALSE)	||
		((fdest	=	fopen(filename,"w") )	==	NULL)	||
		((fsrc	=	fopen(tempfile,"r") )	==	NULL))
	{
		StatusList->AddMessage("ERROR:HardWare Problem :: Cannot Save Chages to File <"+filename+">");
		return;
	}
	unsigned long	slinenumber	=	1;
	BOOL			endcopy		=	FALSE;
	char			line[MAXIMUMLINELENGTH];
	CString			command;
	while(endcopy	==	FALSE)
	{
		//Initialization of insensitive string without spacebars and tabulators		
		if(slinenumber	==	startblockfileposition)
		{ 
			for(int i = 0;i<templist->GetNumberOfMessages();i++)
			{
				CString command	=	templist->GetMessage(i);
				command			+="\n";
				fputs(command,fdest);
				if(slinenumber <= endblockfileposition)
				{
					fgets(line,MAXIMUMLINELENGTH,fsrc);
				}
				slinenumber++;
			}
		}
		else
		{
			if(fgets(line,MAXIMUMLINELENGTH,fsrc)	==	NULL)
			{
				endcopy = TRUE;
				continue;
			}
			if((slinenumber< startblockfileposition)||(slinenumber >(endblockfileposition+2)))
			{
				fputs(line,fdest);
			}
			slinenumber++;
		}
	}
	
	fclose(fdest);
	fclose(fsrc);
	return ;

}

unsigned long scenario::GetNumberOffClocksInGroup(group *pGroup)
{
	if(pGroup == NULL)
	{
		return -1;
	}
	numberofclocksingroup	=	0;
	if(CheckNumberOfLineInComponents(pGroup) == -1)
	{
		return -1;
	}
	return 0;	
}




int scenario::CheckNumberOfLineInComponents(group *wgroup)
{
	switch(wgroup->GetType())
	{
		case W_FRAME:
					{
						frame *selectedframe	=	(frame*) wgroup;
						for(int i=0;i<selectedframe->GetNumberOfComponents();i++)
						{
							CString compname	=	selectedframe->GetComponentName(i);
							int		compseq		=	selectedframe->GetComponentSequences(i);
							int		pos			=	GetNumberOfGroupByName(compname,W_DEFAULT,FALSE);
							for(int ii=0;ii<compseq;ii++)
							{
								if(CheckNumberOfLineInComponents(groups[pos])	==	-1)
								{
									return -1;
								}
							}
						}
					};break;
		case W_COMPLEX:
					{
						complex_group *selectedcomplex	=	(complex_group*) wgroup;
						for(int i=0;i<selectedcomplex->GetNumberOfComponents();i++)
						{
							CString compname	=	selectedcomplex->GetComponentName(i);
							int		compseq		=	selectedcomplex->GetComponentSequences(i);
							int		pos			=	GetNumberOfGroupByName(compname,W_DEFAULT,FALSE);
							for(int ii=0;ii<compseq;ii++)
							{
								if(CheckNumberOfLineInComponents(groups[pos])	==	-1)
								{
									return -1;
								}
							}
						}
					};break;
		case W_SIMPLE:
					{
						simple_group*	grp	=	(simple_group*) wgroup;
						if(grp->GetGroupStatus() == FALSE)
						{
							StatusList->AddMessage("ERROR:Cannot Generate Vector File");
							StatusList->AddMessage("ERROR:Group <"+grp->GetName()+"is not defined");
							return -1;
						}
						numberofclocksingroup	+=	grp->GetClock();
					};break;
	}
	return 0;
}


void scenario::OpendialogWritingVector()
{
	wsdialogexist		=	TRUE;
	wsdialog			=	new WritingSatusDialog();
	wsdialog->Create		(IDD_FRAMEWRITESTATUS);
	wsdialog->ShowWindow	(SW_SHOW);

}

void scenario::ClosedialogWritingVector()
{
	wsdialogexist		=	FALSE;
	delete wsdialog;
}



int scenario::OnSavealltovectorfile(CString directory,mymessages* files)
{
	for(int i=0;i<MAXIMUM_GROUPS;i++)
	{
		if((groups[i]	!=	NULL)&&(groups[i]->GetType() == W_FRAME))
		{
//----------------------------------------------------------------------------------------
			frame	*pframe	=	(frame*)	groups[i];
			CString filen	=directory+GetNameOnly() +"_"+pframe->GetName()+".txt";
			files->AddMessage(filen);
			files->AddMessage(pframe->GetName());
			files->AddMessage(pframe->GetHTotal());
			files->AddMessage(pframe->GetVTotal());
			files->AddMessage(pframe->GetCompressor());
			files->AddMessage(pframe->GetVTotal_2());
			files->AddMessage(pframe->GetNFS());
			FILE *pfile	=	fopen(filen,"w");
			if(pfile == NULL)
			{
				StatusList->AddMessage("ERROR:cannot create file"+filen);
				return -1;
			}
			if(GenerateVectorFileFromFrame(groups[i]->GetName(),pfile)	==	-1)
			{
				fclose(pfile);
				return -1;
			}
			fclose(pfile);
//----------------------------------------------------------------------------------------
		}
	}
	return 0;
}








CString scenario::GetFrameHTotal(CString framename)
{
	int selected		=	GetNumberOfGroupByName(framename,0,FALSE);
	if(selected	==	-1)
	{
		return "-1";
	}
	if(groups[selected]->GetType()	!=	W_FRAME)
	{
		StatusList->AddMessage("ERROR:Selected Item  <"+framename+"> is not frame");
		return "-1";
	}
	frame*	pframe		=	(frame*) groups[selected];
	return pframe->GetHTotal();
}

CString scenario::GetFrameVTotal(CString framename)
{
	int selected		=	GetNumberOfGroupByName(framename,0,FALSE);
	if(selected	==	-1)
	{
		return "-1";
	}
	if(groups[selected]->GetType()	!=	W_FRAME)
	{
		StatusList->AddMessage("ERROR:Selected Item  <"+framename+"> is not frame");
		return "-1";
	}
	frame*	pframe		=	(frame*) groups[selected];
	return pframe->GetVTotal();

}

CString scenario::GetFrameVTotal_2(CString framename)
{
	int selected		=	GetNumberOfGroupByName(framename,0,FALSE);
	if(selected	==	-1)
	{
		return "-1";
	}
	if(groups[selected]->GetType()	!=	W_FRAME)
	{
		StatusList->AddMessage("ERROR:Selected Item  <"+framename+"> is not frame");
		return "-1";
	}
	frame*	pframe		=	(frame*) groups[selected];
	return pframe->GetVTotal_2();

}

CString scenario::GetOriginalTimeType()
{
	return OriginalTimeType;
}

CString scenario::GetCurrentTimeType()
{
	return ( TimeDivider == 1000 )? "ms" : OriginalTimeType;
}

void scenario::ChangeTimeDivider()
{
	if ( TimeDivider == 1000 )
	{
		TimeDivider = 1;
	}
	else
	{
		TimeDivider = 1000;
	}
}

__int64 scenario::ConvertTimeToOriginalType( __int64 TimeValue )
{
	return TimeValue * TimeDivider;
}

CString scenario::GetFrameNFS(CString framename)
{
	int selected		=	GetNumberOfGroupByName(framename,0,FALSE);
	if(selected	==	-1)
	{
		return "-1";
	}
	if(groups[selected]->GetType()	!=	W_FRAME)
	{
		StatusList->AddMessage("ERROR:Selected Item  <"+framename+"> is not frame");
		return "-1";
	}
	frame*	pframe		=	(frame*) groups[selected];
	return pframe->GetNFS();

}
CString scenario::GetFrameSubRes(CString framename)
{
	int selected		=	GetNumberOfGroupByName(framename,0,FALSE);
	if(selected	==	-1)
	{
		return "-1";
	}
	if(groups[selected]->GetType()	!=	W_FRAME)
	{
		StatusList->AddMessage("ERROR:Selected Item  <"+framename+"> is not frame");
		return "-1";
	}
	frame*	pframe		=	(frame*) groups[selected];
	return pframe->GetSubRes();

}


HTREEITEM scenario::InsertItem(CTreeCtrl* _tree, CString sname, HTREEITEM parent, int _image, int _subimage)
{
	HTREEITEM	res;
	HTREEITEM	Temp	=	_tree->GetNextItem(parent,TVGN_CHILD);
	while(1	==	1)
	{
		if(Temp	==	NULL)
		{
			res	=	 _tree->InsertItem(sname,_image,_subimage,parent);
			_tree->SetItemData(res,TreeNumber);
			return res;
		}
		DWORD	result	=	_tree->GetItemData(Temp);
		if(result == LastTreeNumber)
		{
			_tree->SetItemText	(Temp,sname);
			_tree->SetItemImage	(Temp,_image,_subimage);
			_tree->SetItemData	(Temp,TreeNumber);
			return Temp;
		}
		else
		{
			Temp	=	_tree->GetNextItem(Temp,TVGN_NEXT);
		}
	}
	return res;
}

void scenario::CreateGroupOfWavesignalsForEachGroupInScenarioSignls()
{
	for ( int i = 0; i < globalsignals->GetNumberOfSignals(); i++ )
	{
		if ( globalsignals->GetType( i ) == GROUP_OF_SIGNALS )
		{
			CreateGroupOfWavesignalsForEachSimpleGroupInScenario( globalsignals->GetSignalName( i ) );
		}
	}
}

void scenario::CreateGroupOfWavesignalsForEachSimpleGroupInScenario( CString NameOfWavesignalsGroup )
{
	simple_group* ChosenGroup;
	GroupOfWavesignals* NewGroupOfWavesignals;
	for (int i = 0; i < numberofgroups; i++ )
	{
		if ( groups[i]->GetType() == W_SIMPLE )
		{
			ChosenGroup = ((simple_group*)groups[i]);
			NewGroupOfWavesignals = new GroupOfWavesignals( StatusList );
			NewGroupOfWavesignals->FillDataOfWavesignalGroup( NameOfWavesignalsGroup, globalsignals->GetSignalNumber( NameOfWavesignalsGroup ), ChosenGroup);
			ChosenGroup->ReallocateWaveSignals();
			ChosenGroup->AddSignal( NewGroupOfWavesignals );
		}
	}
}

int ScenarioSignals::SetShowSignalsAtUngroup(int i)
{
	for (int j = SignalsInGroup[i]->GetCount() - 1 ; j > -1 ; j--)
		AddShowSignal(SignalsInGroup[i]->GetAt(j));
	return SignalsInGroup[i]->GetCount();
}

void scenario::Ungroup()
{
	int Y, Count;
	for ( int i=0; i < globalsignals->GetNumberOfSignals(); )
    {
		if( globalsignals->CheckIfSignalMarked( i ) == TRUE && globalsignals->GetType(i) == GROUP_OF_SIGNALS )
		{
			// Here I will add...
			Count = globalsignals->SetShowSignalsAtUngroup(i);
			DeleteSignal( i );
		}
		else
			i++;
    }
	InitGraphData( 
        &mygraphdata,
        mygraphdata.GetGroupName(),
        mygraphdata.globaloffset,
        mygraphdata.globaldelta,
        mygraphdata.windowdelta );
}

void scenario::DeleteMarkedSignalsPermanently()
{
	for ( int i=0; i < globalsignals->GetNumberOfSignals(); )
	{
		if( globalsignals->CheckIfSignalMarked( i ) == TRUE )
		{
			DeleteSignal( i );
		}
		else
		{
			i++;
		}
	}
	for ( int i = 0; i < globalsignals->GetNumberOfSignals(); )
	{
		if( globalsignals->GetType( i ) == GROUP_OF_SIGNALS && globalsignals->GetSignalsInGroup( i )->GetCount() < 2 )
		{
			if (  globalsignals->GetSignalsInGroup( i )->GetCount() == 1 )
			{
				globalsignals->AddShowSignal( globalsignals->GetSignalsInGroup( i )->GetAt( 0 ) );
			}
			DeleteSignal( i );
		}
		else
		{
			i++;
		}
	}
	InitGraphData( &mygraphdata, mygraphdata.GetGroupName(), mygraphdata.globaloffset, mygraphdata.globaldelta, mygraphdata.windowdelta);
}

void scenario::DeleteSignal( int SignalNumber )
{
	simple_group* ChosenGroup;
	globalsignals->DeleteSignalFromScenarioSignals( SignalNumber );
	for (int i = 0; i < numberofgroups; i++ )
	{
		if ( groups[i]->GetType() == W_SIMPLE )
		{
			ChosenGroup = ((simple_group*)groups[i]);
			ChosenGroup->ReallocateWaveSignals();
			ChosenGroup->RefreshWavesignalsGroups();
		}
	}
}

unsigned __int64 scenario::GetPositionOfFirstGroupAfterGlobalPosition( group *Group, unsigned __int64 GlobalPosition, unsigned __int64 StartPosition )
{
	switch(Group->GetType())
	{
		case W_FRAME:
					{
						frame *SelectedFrame	=	(frame*) Group;
						for(int i=0;i<SelectedFrame->GetNumberOfComponents();i++)
						{
							CString CompName	=	SelectedFrame->GetComponentName(i);
							int		CompSeq		=	SelectedFrame->GetComponentSequences(i);
							int		Pos			=	GetNumberOfGroupByName(CompName,W_DEFAULT,FALSE);
							for(int ii=0;ii<CompSeq;ii++)
							{
								StartPosition	=	GetPositionOfFirstGroupAfterGlobalPosition ( groups[Pos], GlobalPosition, StartPosition );
								if ( StartPosition > GlobalPosition )
								{
									return StartPosition;
								}
							}
						}
					};break;
		case W_COMPLEX:
					{
						complex_group *SelectedComplex	=	(complex_group*) Group;
						for(int i=0;i<SelectedComplex->GetNumberOfComponents();i++)
						{
							CString CompName	=	SelectedComplex->GetComponentName(i);
							int		CompSeq		=	SelectedComplex->GetComponentSequences(i);
							int		Pos			=	GetNumberOfGroupByName(CompName,W_DEFAULT,FALSE);
							for(int ii=0;ii<CompSeq;ii++)
							{
								StartPosition	=	GetPositionOfFirstGroupAfterGlobalPosition ( groups[Pos], GlobalPosition, StartPosition );
								if ( StartPosition > GlobalPosition )
								{
									return StartPosition;
								}
							}
						}
					};break;
		case W_SIMPLE:
					{
						simple_group*	SimpleGroup	= (simple_group*) Group;
						StartPosition += SimpleGroup->GetClock()/TimeDivider;
					};break;
	}
	return StartPosition;
}

void scenario::ExcludeChangesByString( CArray< Signal, Signal > &Signals, long LineType )
{
	long NumberOfSignalsFromLog = Signals.GetCount();
	bool **MarksForSignals = new bool*[NumberOfSignalsFromLog];
	for ( int i = 0; i < NumberOfSignalsFromLog; i++ )
	{
		MarksForSignals[i] = new bool[Signals[i].Changes.GetCount()];
		memset( MarksForSignals[i], 0, sizeof(bool)*Signals[i].Changes.GetCount() );
	}
		
	MarkIncludedChanges( Signals, MarksForSignals, LineType );
	
	RemoveUnmarkedChanges( Signals, MarksForSignals, LineType );

	DeleteEmptySignals( Signals );
	
	for ( int i = 0; i < NumberOfSignalsFromLog; i++ )
	{
		delete MarksForSignals[i];
	}
	delete MarksForSignals;
}

simple_group * scenario::GetFirstSimpleGroup()
{
	for ( int i = 0; i < numberofgroups; i++ )
	{
		if ( groups[i]->GetType() == W_SIMPLE )
		{
			return (simple_group*)groups[i];
		}
	}
	return NULL;
}

void scenario::MarkIncludedChanges( CArray< Signal, Signal > &Signals, bool **MarksForSignals, long LineType )
{
	if ( GetFileExtension( GetFileName() ) != "log" )
	{
		throw WrongFileExtensionException();
	}
	CString FirstWord;
	simple_group *ScenarioGroup = GetFirstSimpleGroup();
	int j;
	long NumberOfSignalsFromLog = Signals.GetCount();
	long NumberOfSignalsFromScenario = globalsignals->GetNumberOfSignals	();
	for ( int i = 0; i < NumberOfSignalsFromScenario; i++ )
	{
		if ( globalsignals->GetType( i ) != LineType )
		{
			continue;
		}
		j = 0;
		long Position = globalsignals->GetOriginalName(i).FindOneOf(" \t\r\n");
		FirstWord = globalsignals->GetOriginalName(i).Mid(0, ( Position < 0 ) ? globalsignals->GetOriginalName(i).GetLength() : Position );
		while ( j < NumberOfSignalsFromLog )
		{
			if ( Signals[j].Name == FirstWord && Signals[j].SignalType == LineType )
			{
				break;
			}
			j++;
		}
		if ( j < NumberOfSignalsFromLog )
		{
			ScenarioGroup->GetPointerToWavesignalByIndex( i )->MarkIncludedChanges( Signals[j], MarksForSignals, j );
		}
	}
}

void scenario::RemoveUnmarkedChanges( CArray< Signal, Signal > &Signals, bool **MarksForSignals, long LineType )
{
	for ( int k = 0; k < Signals.GetCount(); k++ )
	{
		if ( Signals[k].SignalType != LineType )
		{
			continue;
		}
		for ( int j = 0, i = 0; j < Signals[k].Changes.GetCount();i++)
		{
			if ( MarksForSignals[k][i] == false )
			{
				Signals[k].Changes.RemoveAt(j);
			}
			else
			{
				j++;
			}
		}
	}
}

void scenario::DeleteEmptySignals( CArray< Signal, Signal > &Signals )
{
	for ( int j = 0; j < Signals.GetCount();)
	{
		if ( Signals[j].Changes.GetCount() == 0 )
		{
			Signals.RemoveAt(j);
		}
		else
		{
			j++;
		}
	}
}

void scenario::ExcludeUnusedStringsByPreciseName( CArray< Signal, Signal > &Signals, long LineType )
{
	long NumberOfSignalsFromLog = Signals.GetCount();
	long NumberOfSignalsFromScenario = globalsignals->GetNumberOfSignals();
	bool *MarksForSignals = new bool[NumberOfSignalsFromLog];
	memset( MarksForSignals, 0, NumberOfSignalsFromLog * sizeof(bool) );
	for ( int i = 0; i < NumberOfSignalsFromScenario; i++ )
	{
		if ( globalsignals->GetType( i ) != LineType )
		{
			continue;
		}
		for ( int j = 0; j < NumberOfSignalsFromLog; j++ )
		{
			if ( MarksForSignals[j] == true || Signals[j].SignalType != LineType )
			{
				continue;
			}
			if ( Signals[j].Name == globalsignals->GetOriginalName(i) )
			{
				MarksForSignals[j] = true;
			}
		}
	}
	for ( int j = 0, i = 0; j < Signals.GetCount();i++)
	{
		if ( MarksForSignals[i] == false && Signals[j].SignalType == LineType )
		{
			Signals.RemoveAt(j);
		}
		else
		{
			j++;
		}
	}
	delete MarksForSignals;
}

void scenario::ExcludeUnusedStringsByWord( CArray< Signal, Signal > &Signals, long LineType )
{
	long NumberOfSignalsFromLog = Signals.GetCount();
	long NumberOfSignalsFromScenario = globalsignals->GetNumberOfSignals();
	bool *MarksForSignals = new bool[NumberOfSignalsFromLog];
	memset( MarksForSignals, 0, NumberOfSignalsFromLog * sizeof(bool) );
	for ( int i = 0; i < NumberOfSignalsFromScenario; i++ )
	{
		if ( globalsignals->GetType( i ) != LineType )
		{
			continue;
		}
		for ( int j = 0; j < NumberOfSignalsFromLog; j++ )
		{
			if ( MarksForSignals[j] == true || Signals[j].SignalType != LineType )
			{
				continue;
			}
			long Position = Signals[j].Name.FindOneOf(" \t\r\n" );
			if ( Signals[j].Name.Mid( 0, (Position < 0 )? Signals[j].Name.GetLength() : Position ) == globalsignals->GetOriginalName(i) )
			{
				MarksForSignals[j] = true;
			}
		}
	}
	for ( int j = 0, i = 0; j < Signals.GetCount();i++)
	{
		if ( MarksForSignals[i] == false && Signals[j].SignalType == LineType )
		{
			Signals.RemoveAt(j);
		}
		else
		{
			j++;
		}
	}
	delete MarksForSignals;
}

void scenario::CutReturnFreeSpace()
{
	if ( FreeSpaceCutOff == false )
	{
		CutFreeSpace();
	}
	else
	{
		ReturnFreeSpace();
	}
	FreeSpaceCutOff = !FreeSpaceCutOff;
}

void scenario::ReturnFreeSpace()
{
	for ( int i = 0; i < numberofgroups; i++ )
	{
		if ( groups[i]->GetType() == W_SIMPLE )
		{
			((simple_group*)groups[i])->ReturnFreeSpace();
		}
	}
}

void scenario::CutFreeSpace()
{
	for ( int i = 0; i < numberofgroups; i++ )
	{
		if ( groups[i]->GetType() == W_SIMPLE )
		{
			((simple_group*)groups[i])->CutFreeSpace();
		}
	}
}

void scenario::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		ar<<CutUnUsedPartForScriptFile( GetFileName() );
		StatusList->AddMessage( CutUnUsedPartForScriptFile( GetFileName() ) );
		globalsignals->Serialize(ar);
		ar<<LogReadType.TypeOfBracketLines;
		ar<<LogReadType.TypeOfNoBracketLines;
		ar<<TimeDivider;
		ar<<FreeSpaceCutOff;
	}
	else
	{
		ZWaveeditorApp	*CWinapp	=	(ZWaveeditorApp*) AfxGetApp();
		CString scriptdir	;//		=	CWinapp->ScriptDirectory+"\\";
		CFile *pf	=	ar.GetFile();
		if(pf == NULL)
		{
			scriptdir	= "";
		}
		else
		{
			scriptdir		=	pf->GetFilePath();
			int namelen		=	pf->GetFileName().GetLength();
			scriptdir		=	scriptdir.Mid(0,scriptdir.GetLength()-namelen);
		}

		ar>>filename;
		if(CheckIfFullScriptPath(filename) == FALSE)
		{
			filename=	scriptdir+filename;
		}
		globalsignals->Serialize(ar);
		ar>>LogReadType.TypeOfBracketLines;
		ar>>LogReadType.TypeOfNoBracketLines;
		ar>>TimeDivider;
		ar>>FreeSpaceCutOff;
		FreeSpaceCutOff = !FreeSpaceCutOff;
	}
}

CString scenario::CutUnUsedPartForScriptFile(CString OriginalName )
{
	ZWaveeditorApp	*pWinapp	=	(ZWaveeditorApp*) AfxGetApp();
	CString scriptdir			=	pWinapp->DocumentDirectory;
	CString Name = OriginalName;
	Name.MakeLower();
	int pos	=	Name.Find(scriptdir);
	if(pos	>=0)
	{
		OriginalName = OriginalName.Mid(scriptdir.GetLength()+1);
	}
	return OriginalName;
}

BOOL scenario::CheckIfFullScriptPath(CString name)
{
	return ( name.Find(":") >= 0 );
}

unsigned __int64 scenario::GetFirstTimingChangeAfterTime(int GroupNum, int SignalNum, unsigned __int64 Time)
{
	unsigned __int64 Disp(0);
	return GetFirstTimingChangeAfterTime(GroupNum, SignalNum, Time, Disp);
}

unsigned __int64 scenario::GetFirstTimingChangeAfterTime(int GroupNum, int SignalNum, unsigned __int64 Time, unsigned __int64& Disp)
{
	if ( groups[GroupNum]->GetType() == W_SIMPLE )
	{
		__int64 Result = ((simple_group *)groups[GroupNum])->GetPointerToWavesignalByIndex(SignalNum)
												 ->GetFirstTimingChangeAfterTime( Time - Disp );
		Disp += ((simple_group *)groups[GroupNum])->GetClock();
		return Result;
	}
	if ( groups[GroupNum]->GetType() == W_FRAME )
	{
		frame* Frame = (frame *)groups[GroupNum];
		for (int i = 0 ; i < Frame->GetNumberOfComponents() ; i++)
		{
			int Num = GetNumberOfGroupByName(Frame->GetComponentName(i), 3 ,FALSE);

			for (int j = 0 ; j < Frame->GetComponentSequences(i) ; j++)
			{
				unsigned __int64 FirstChange = GetFirstTimingChangeAfterTime(Num, SignalNum, Time, Disp);
				if ( FirstChange != -1 )
					return FirstChange;
			}
		}
		return -1;
	}
	//Due to the fact that the frame and the group has the same set of methods and data,
	//but does not have a general class with the data that should be duplicated on the type of test
	if ( groups[GroupNum]->GetType() == W_COMPLEX )
	{
		complex_group* ComplexGroup = (complex_group *)groups[GroupNum];
		for (int i = 0 ; i < ComplexGroup->GetNumberOfComponents() ; i++)
		{
			int Num = GetNumberOfGroupByName(ComplexGroup->GetComponentName(i), 3 ,FALSE);

			for (int j = 0 ; j < ComplexGroup->GetComponentSequences(i) ; j++)
			{
				unsigned __int64 FirstChange = GetFirstTimingChangeAfterTime(Num, SignalNum, Time, Disp);
				if ( FirstChange != -1 )
					return FirstChange;
			}
		}
		return -1;
	}
}

void scenario::SortSelectedWavesByVal( std::vector<int> &SelectedWaves, CString& GroupName)
{
	if ( *std::max_element( SelectedWaves.begin(), SelectedWaves.end() ) >= globalsignals->GetNumberOfSignals() )
	{
		throw InvalidArray();
	}
	std::vector<SignalForSortByVal> SignalsForSort;
	SignalForSortByVal Temp;
	int SizeOfArray = SelectedWaves.size();
	int GroupNum = GetNumberOfGroupByName( GroupName, 3 ,FALSE);
	__int64 GreenMark = mygraphdata._1stmark.x_true;

	for ( int i = 0; i < SizeOfArray; i++ )
	{
		unsigned __int64 Result = GetFirstTimingChangeAfterTime( GroupNum, SelectedWaves[i], GreenMark );
		if ( Result == -1)
			Result = 0x7FFFFFFFFFFFFFFF;
		Temp.Val = Result;
		Temp.SignalNumber = SelectedWaves[i];
		SignalsForSort.push_back( Temp );
	}
	std::stable_sort( SignalsForSort.begin(), SignalsForSort.end() );
	for ( int i = 0; i < SizeOfArray; i++ )
	{
		SelectedWaves[i] = SignalsForSort[i].SignalNumber;
	}
}

//Functor for comparing signals by order
class CompareSignalsByOrder
{
public:
    CompareSignalsByOrder( const scenario & Scenario ) :
    m_Scenario( Scenario )
    {
    }

    bool operator() ( const int FirstSignal, const int SecondSignal )
    {
        //casting to unsigned is made for transforming -1 to maximal value (if error happened). 
        unsigned int FirstSignalOrder = 
            static_cast<unsigned int>( m_Scenario.globalsignals->GetSignalOrder( FirstSignal ) );
        unsigned int SecondSignalOrder = 
            static_cast<unsigned int>( m_Scenario.globalsignals->GetSignalOrder( SecondSignal ) );
        return ( FirstSignalOrder < SecondSignalOrder );
    }

    const scenario & m_Scenario;
};

void scenario::OnSortSelectedWavesByVal(CString& GroupName)
{
	std::vector<int> SelectedWaves, OrdersOfSelectedWaves;
	globalsignals->GetSelectedWaves( SelectedWaves );
	int NumberOfSelectedWaves = SelectedWaves.size();
	for ( int i = 0; i < NumberOfSelectedWaves; i++ )
    {
		OrdersOfSelectedWaves.push_back( globalsignals->GetSignalOrder(SelectedWaves[i]) );
    }

    //Sorting waves by orders to avoid unnecessary replacing
    std::sort( SelectedWaves.begin(), SelectedWaves.end(), CompareSignalsByOrder( *this ) );

	SortSelectedWavesByVal( SelectedWaves, GroupName );

	//Sorting orders for comparison with sorted waves by name later
	std::sort( OrdersOfSelectedWaves.begin(), OrdersOfSelectedWaves.end() );
	for ( int i = 0; i < NumberOfSelectedWaves; i++ )
	{
		globalsignals->ChangeSignalsPositions( SelectedWaves[i], globalsignals->GetSignalNumber( OrdersOfSelectedWaves[i] ) );
	}
}
